简体   繁体   中英

running a os.system / subprocess.call returns Syntax error

I have this bash command I want to run from Python2.7:

time ( s=172.20.16 ; for i in $(seq 1 254) ; do ( ping -n -c 1 -w 1 $s.$i 1>/dev/null 2>&1 && printf "%-16s %s\n" $s.$i responded ) & done ; wait ; echo ) 

I tried running it like this:

cmd = 'time ( s=172.20.16 ; for i in $(seq 1 254) ; do ( ping -n -c 1 -w 1 $s.$i 1>/dev/null 2>&1 && printf "%-16s %s\n" $s.$i responded ) & done ; wait ; echo )'

#1. subprocess.call(cmd.split())
#2. subprocess.call(cmd, shell=True)
#3. os.system(cmd)

But all returned /bin/sh: 1: Syntax error: word unexpected (expecting ")") , while running it from bash worked prefectly. I also tried adding a /bin/bash to the head of the command, but that didn't work.

When using os.system('bash "{}"'.format(cmd)) it didn't crash with the previous error, but the loop unfolded incorecctly (it printed 1..254 instead of using them as the IP suffix)

I managed to make it work by saving the command in a bash script and then calling the script from python, but I would rather do that directly. What is the problem here?

shell=True uses /bin/sh . /bin/sh is not bash .

Leaving all the problems with the shell script in place, but invoking it with bash, would look like the following:

cmd = 'time ( s=172.20.16 ; for i in $(seq 1 254) ; do ( ping -n -c 1 -w 1 $s.$i 1>/dev/null 2>&1 && printf "%-16s %s\n" $s.$i responded ) & done ; wait ; echo )'
subprocess.call(['bash', '-c', cmd])

Rewriting it to actually be a better shell script might instead look like:

cmd = r'''
time {
  s=172.20.16
  for ((i=1; i<=254; i++)); do
    { ping -n -c 1 -w 1 "$s.$i" >/dev/null 2>&1 && \
      printf "%-16s %s\n" "$s.$i" "responded"
    } &
  done
  wait
  echo
}
'''
subprocess.call(['bash', '-c', cmd])

Note that we're using { ...; } { ...; } , not ( ... ) , for grouping (thus avoiding more subshell creations than necessary); and that we're always quoting substitutions.

you are splitting by space to construct the array of commands/parameters for the suprocess call method; but notice that there are parameters that include spaces, so it should count as a single parameter, not two (ie this one: "%-16s %s\\n" )

Try using subprocess as per this link Running Bash commands in Python

import subprocess
subprocess.call("{}".format(cmd).split())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM