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
2 Answers 2
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.
5 Comments
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?. Think: what is the difference between subprocess.Popen(cmd)` and subprocess.Popen(cmd).wait()` and which one is closer to subprocess.call(cmd).subprocess.call(cmd) seems closer to subprocess.Popen.wait(). The python script now executes as expected, cheers.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)
call([path, flags.strip(), ip_addr])