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)
Asked By: Raj

||

Answers:

There are a couple of ways to solve this:

  1. 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)]
  1. 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)
  1. 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.

Answered By: Lexpj

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.

Answered By: tripleee
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.