5

I'm trying to execute this command from a python script using subprocess: sleep 10 && sudo /etc/init.d/tractor-blade restart &

I want the python script to finish (return code 0). Then, 10 seconds later I wish the command to get executed.

This is what I have:

import sys, subprocess
command = ['sleep', '10', '&&', 'sudo', '/etc/init.d/tractor-blade', 'restart' '&']
p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

# Catch stdout
sys.stdout.flush()
for line in iter(p.stdout.readline, b''):
    print(">>> " + line.rstrip())

But this is what happens:

>>> sleep: invalid time interval `&&'
>>> sleep: invalid time interval `sudo'
>>> sleep: invalid time interval `/etc/init.d/tractor-blade'
>>> sleep: invalid time interval `restart'
>>> sleep: invalid time interval `&'
>>> Try `sleep --help' for more information.

I am guessing my formatting is wrong?

I need to make the python script complete before the command is being executed, which is why I am trying to add a delay to the command. My sudoers allows for this `tractor-blade' to get executed with NOPASSWD, thus does not require a password.

fredrik
  • 9,631
  • 16
  • 72
  • 132
  • possible duplicate of [Launch a shell command with in a python script, wait for the termination and return to the script](http://stackoverflow.com/questions/325463/launch-a-shell-command-with-in-a-python-script-wait-for-the-termination-and-ret) – devnull May 05 '14 at 16:02
  • I do NOT want to wait for termination. I want to delay the execution of the command and exit the python script. Then I want the command to get executed, 10 seconds after the python script has exited. – fredrik May 05 '14 at 16:06
  • Yes, it is still the same problem. You do NOT need to `wait`. All you need is `shell = True`. – devnull May 05 '14 at 16:10

2 Answers2

7

this is because subprocess can work in two modes: either you fork() the process specified by the tuple passed as argument, or you execute the string with a shell. The difference is the shell argument. So what you might want to do is:

command = "sleep 10 && sudo /etc/init.d/tractor-blade restart"
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT)

or:

time.sleep(10)
command = ['sudo', '/etc/init.d/tractor-blade', 'restart' '&']
subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

from the documentation:

The shell argument (which defaults to False) specifies whether to use the shell as the program to execute. If shell is True, it is recommended to pass args as a string rather than as a sequence.

zmo
  • 24,463
  • 4
  • 54
  • 90
0

The way the API works is, the first element in command is the program that subprocess.Popen will invoke. And the rest of that list is parsed and then fed into that program as arguments. By default, they are not parsed as a shell command.

Santa
  • 11,381
  • 8
  • 51
  • 64