How to read each line in the user input and process the commnad
Question:
I am trying to ping multiple host to check communication. Below is my script and it works fine. I am giving the server names as test226693 test226693 test226825 but would like to give the server name in the new line like below as I have more server list so cannot put everything in each line.
currently it is:
Enter the server name:
test226693 test226745 test226825
Wanted to give the server names like below and get the output and line to print "you are going to do ping test 5 clients.The number 5 will vary based on the input.
test226693
test226745
test226825
test226889
test227082
def ping():
server_names=input("Enter the server name: n")
server_names=server_names.split(" ")
for servers in server_names:
command = f"ping {servers}"
output=subprocess.Popen((command),shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE).communicate()[0]
print(output)
Answers:
There are a couple of ways to solve this:
- You state how many server names you are going to input first, and then looping that amount of times to get all the inputs:
nr_server_names = int(input("How many server names are you going to input?"))
server_names = [input("Enter the server name: n") for _ in range(nr_server_names)]
- You could also have a stopping statement, that will break you out of a continuous loop:
server_name = input("Enter the server name: n")
server_names.append(server_name)
while server_name != "STOP":
server_name = input("Enter the server name: n")
server_names.append(server_name)
- For convenience, if I have a large input, I would put it in a text file and read the text file out. This could be inconvenient in your case, if you specifically want to call some server (e.g. that you do not want to change a text file every time), but if it were the same server names you want to keep calling, this might help out.
with open("servernames.txt","r") as f:
server_names = [server_name.rstrip() for server_name in f.readlines()]
and your servernames.txt
containing
test226693
test226745
test226825
test226889
test227082
I hope this helps you continue.
EDIT:
From the comments, you stated to prefer the second option. The code for that would then in full be:
def ping():
server_names=[]
server_name = input("Enter the server name: n")
while server_name != "STOP":
server_names.append(server_name)
server_name = input()
for servers in server_names:
command = f"ping {servers}"
output=subprocess.Popen((command),shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE).communicate()[0]
print(output)
Then you can input your desired server names, and conclude with "STOP" in order to let the program know you that you are finished with the input.
Requiring interactive I/O makes your script less useful. You can run it like
tr 'n' ' ' <servernames.txt |
python yourscript
but a much better solution is to just have it read the file directly.
import sys
servers = [line.rstrip('n') for line in sys.stdin]
print("will ping", len(servers), "hosts")
for server in servers:
subprocess.run(['ping', '-c', '1', server], check=True)
You would use this simply like
python tripleee.py <servernames.txt
The check=True
keyword argument to subprocess.run
will cause Python to raise an exception if the ping
fails. If you want to continue the script in case of an error, you probably want to add a try
/ except
handler around the subprocess; or simply take out the check=True
(I don’t generally recommend this, though).
Notice also how we always want to avoid shell=True
when we can and prefer to avoid Popen
when we can, like the subprocess
documentation recommends.
I am trying to ping multiple host to check communication. Below is my script and it works fine. I am giving the server names as test226693 test226693 test226825 but would like to give the server name in the new line like below as I have more server list so cannot put everything in each line.
currently it is:
Enter the server name:
test226693 test226745 test226825
Wanted to give the server names like below and get the output and line to print "you are going to do ping test 5 clients.The number 5 will vary based on the input.
test226693
test226745
test226825
test226889
test227082
def ping():
server_names=input("Enter the server name: n")
server_names=server_names.split(" ")
for servers in server_names:
command = f"ping {servers}"
output=subprocess.Popen((command),shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE).communicate()[0]
print(output)
There are a couple of ways to solve this:
- You state how many server names you are going to input first, and then looping that amount of times to get all the inputs:
nr_server_names = int(input("How many server names are you going to input?"))
server_names = [input("Enter the server name: n") for _ in range(nr_server_names)]
- You could also have a stopping statement, that will break you out of a continuous loop:
server_name = input("Enter the server name: n")
server_names.append(server_name)
while server_name != "STOP":
server_name = input("Enter the server name: n")
server_names.append(server_name)
- For convenience, if I have a large input, I would put it in a text file and read the text file out. This could be inconvenient in your case, if you specifically want to call some server (e.g. that you do not want to change a text file every time), but if it were the same server names you want to keep calling, this might help out.
with open("servernames.txt","r") as f:
server_names = [server_name.rstrip() for server_name in f.readlines()]
and your servernames.txt
containing
test226693
test226745
test226825
test226889
test227082
I hope this helps you continue.
EDIT:
From the comments, you stated to prefer the second option. The code for that would then in full be:
def ping():
server_names=[]
server_name = input("Enter the server name: n")
while server_name != "STOP":
server_names.append(server_name)
server_name = input()
for servers in server_names:
command = f"ping {servers}"
output=subprocess.Popen((command),shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE).communicate()[0]
print(output)
Then you can input your desired server names, and conclude with "STOP" in order to let the program know you that you are finished with the input.
Requiring interactive I/O makes your script less useful. You can run it like
tr 'n' ' ' <servernames.txt |
python yourscript
but a much better solution is to just have it read the file directly.
import sys
servers = [line.rstrip('n') for line in sys.stdin]
print("will ping", len(servers), "hosts")
for server in servers:
subprocess.run(['ping', '-c', '1', server], check=True)
You would use this simply like
python tripleee.py <servernames.txt
The check=True
keyword argument to subprocess.run
will cause Python to raise an exception if the ping
fails. If you want to continue the script in case of an error, you probably want to add a try
/ except
handler around the subprocess; or simply take out the check=True
(I don’t generally recommend this, though).
Notice also how we always want to avoid shell=True
when we can and prefer to avoid Popen
when we can, like the subprocess
documentation recommends.