0

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)
Raj
  • 33
  • 5

2 Answers2

1

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.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Below is the error am getting: testserver> tr '\n' ' ' subprocess.run(['ping', '-c', '3', '-n', server], check=True) File "/usr/local/lib/python3.7/subprocess.py", line 481, in run output=stdout, stderr=stderr) subprocess.CalledProcessError: Command '['ping', '-c', '3', '-n', 'test226693 test226745 test226825 ']' returned non-zero exit status 2. – Raj Feb 03 '23 at 06:15
  • Take out the `check=True` if you want to permit errors. But you seem to have mixed your own script with mine; the Python script I posted should simply receive the file name as its argument. – tripleee Feb 03 '23 at 06:21
  • Many thanks it worked.I am new to python.Believe below line is "list comprehension" servers = [line.rstrip('\n') for line in sys.stdin] How do we write this line a normal way.ie with out list comprehension. – Raj Feb 03 '23 at 08:50
  • 1
    `servers = []; for line in sys.stdin: servers.append(line.rstrip('\n'))`. The `rstrip` removes the line terminator (newline) from the end of the line. – tripleee Feb 03 '23 at 08:52
  • Excellent.Many thannks for all your suggestions. – Raj Feb 03 '23 at 09:46
0

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.

Lexpj
  • 921
  • 2
  • 6
  • 15
  • Below is what am doing after your suggestion but it picks the first server and not iterating. server_names=[] def ping(): server_name=input("Enter the server name: \n") server_names.append(server_name) for servers in server_names: command = f"ping {servers}" output=subprocess.Popen((command),shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE).communicate()[0] print(str(output)) ping() – Raj Feb 02 '23 at 11:53
  • Which approach of the 3 suggested did you use? You seem to ask just once for a server name. This means it will only pick up the first server, since `server_names` just consist of 1 `server_name`. The 3 suggested options are meant to replace the code before you iterate over the `server_names` in the for loop. – Lexpj Feb 02 '23 at 12:24
  • I am trying the option 2. But 3rd option is to read from a file.But would like to do ping test by getting the list of server name or copying the list of server names in thhe user input prompt say for example 5 servers and do ping test. Enter the server name: test226693 test226745 test226825 test226889 test227082 test227102 test227159 – Raj Feb 02 '23 at 12:40
  • Editted the answer for you. – Lexpj Feb 02 '23 at 13:45
  • Still having issues after trying your modified script.Its not processing the command(ping) after giving input server names. Still sits in the input.Please see below: Enter the server name: test226693 test226745 test226825 test226889 test227082 test227102 test227159 – Raj Feb 02 '23 at 14:58