3

I am writing a simple python script under Linux to do a batch of concurrent single pings to hosts on my subnet using subprocess.

Manually the command works: ping -c 1 192.168.68.1

The script::

#!/usr/bin/python
from subprocess import call

path = "ping"
flags = "-c 1 "

for i in range(1,3):
    ip_addr = "192.168.68." + str(i)
    args = flags + ip_addr

    print "doing: {} {}".format(path, args)        
    call([path, args])

Commenting out call outputs the expected:

doing: ping -c 1 192.168.68.1
doing: ping -c 1 192.168.68.2

With call(), the script seems to call ping but with unknown arguments. Output as follows:

doing: ping -c 1 192.168.68.1
Usage: ping [-aAbBdDfhLnOqrRUvV64] [-c count] [-i interval] [-I interface]
        [-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos]
        [-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option]
        [-w deadline] [-W timeout] [hop1 ...] destination
Usage: ping -6 [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface]
         [-l preload] [-m mark] [-M pmtudisc_option]
         [-N nodeinfo_option] [-p pattern] [-Q tclass] [-s packetsize]
         [-S sndbuf] [-t ttl] [-T timestamp_option] [-w deadline]
         [-W timeout] destination
doing: ping -c 1 192.168.68.2
Usage: ping [-aAbBdDfhLnOqrRUvV64] [-c count] [-i interval] [-I interface]
        [-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos]
        [-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option]
        [-w deadline] [-W timeout] [hop1 ...] destination
Usage: ping -6 [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface]
         [-l preload] [-m mark] [-M pmtudisc_option]
         [-N nodeinfo_option] [-p pattern] [-Q tclass] [-s packetsize]
         [-S sndbuf] [-t ttl] [-T timestamp_option] [-w deadline]
         [-W timeout] destination

It seems ping is being called twice for each iteration with different args to what I expect. I note the -6 argument ping complains about.
I would appreciate any help, particularly with regard to using call() properly.

Update:
Added bash script I'm attempting to emulate:

#!/bin/bash
for ip in $(seq 1 2); do
    ping -c 1 192.168.68.$ip &
done
1
  • 3
    call([path, flags.strip(), ip_addr]) Commented May 22, 2016 at 5:47

2 Answers 2

3

The arguments passed to the function call should each be a single element in a list, as such:

call(['ping','-c','1','192.168.68.2'])

I could not reproduce the 'double printing' in my environment.

Sign up to request clarification or add additional context in comments.

5 Comments

Hi Pablo, I have tried flags = ["-c", "1"] and then tried unpacking in the call() call([path, *flags, ip_addr]) I get syntax error. Is it not possible to unpack within the array?
@user1330734: it is Python 3.5+ syntax.
@J.F. Sebastian Interestingly, the python code seem to be synchronous i.e. each ping call seems to wait for previous to complete. In contrast, the forking bash script I added above takes about 5 seconds to do IP range 1-254.
@user1330734 read the docs for subprocess.call(cmd). Think: what is the difference between subprocess.Popen(cmd)` and subprocess.Popen(cmd).wait()` and which one is closer to subprocess.call(cmd).
@J.F. Sebastian Thank you kindly for pointing me to the right place. In order to achieve concurrency, I need to call subprocess.Popen(cmd). subprocess.call(cmd) seems closer to subprocess.Popen.wait(). The python script now executes as expected, cheers.
0

As @Pablo mentioned flagsand path variables should be a list elements, so before calling the call method just convert your command string to list:

path = "ping"
flags = "-c 1"
cmd_list = [path] # convert string to list
cmd_list = cmd_list + flags.split(' ') # converting your flags string to list elements

call(cmd_list)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.