0

i've just created a software in python which should schedule several commands from shell. (ps: i'm working on linux) By the way, i've created the following function to launch processes:

def exec_command(cmd):
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setsid)
pid = process.pid
print '----------launched process with PID: ', pid 
return pid

After this i use the pid to check if the process goes on zombie's state and in that case a kill it. Sometime everything works just fine but there is a case in which the process launched doesn't do anything. The process i'm talking about is: sh /home/ubuntu/programs/data-integration/kitchen.sh -file=/home/ubuntu/TrasformazioneAVM/JobAVM.kjb -level=Basic -param:processName=avm
If i launch it by shell everything works perfectly but if i do it with my function i can see the process on the system monitor (or by shell with the "top" command) but nothing appens (i check the memory usage and cpu usage which is usually really high but not in this case). Any body has any ideas ?

giogix
  • 769
  • 1
  • 12
  • 32

2 Answers2

1
stdout=subprocess.PIPE

Here is the culprit. You're redirecting your child process output to a pipe, but you aren't reading from that pipe.

You can either read from it (if you need output that process creates), or remove redirection altogether.

Edit:

If you wish to redirect output to /dev/null, given the fact that you're launching your command through shell (shell=True) anyway, the simplest solution would be to append > /dev/null to cmd string. If it's also printing to stderr, then you need >/dev/null 2>&1.

A better solution, that doesn't require launching your command through shell, would be as follows:

If you're on Python 3.3 or higher, just pass subprocess.DEVNULL constant:

subprocess.Popen(cmd, stdout=subprocess.DEVNULL, shell=True, preexec_fn=os.setsid)

If not, or you want to maintain backward compatibility, just open /dev/null and pass it:

subprocess.Popen(cmd, stdout=open(os.devnull, "w"), shell=True, preexec_fn=os.setsid)
WGH
  • 3,222
  • 2
  • 29
  • 42
  • I think that i have to create a pipe because when i launch the process many pids are generated and i when a kill one of these i want that all the proccesses connected die – giogix Feb 06 '14 at 10:51
  • @user2637212 you don't have to use pipes to do that. It's more like side-effect that child receives SIGPIPE and dies once it tries to write to pipe that's closed on the other end. You can use process groups, for example. Remember that pressing ^C in console interrupts all children? It's implemented by sending SIGINT to entire process group. You can do that, too. – WGH Feb 06 '14 at 11:09
  • So what do you suggest to write instead of stdout=subprocess.PIPE ? – giogix Feb 06 '14 at 11:24
  • 1
    @user2637212 Do you need the output that program prints? If you just need to see it yourself, remove stdout argument (or set it to None). Output will be printed to your shell. If you don't need the output at all, you can redirect it to /dev/null by opening it for writing and passing resulting file object. If your python script needs to interpret output somehow (parse it, etc), it will be somewhat more difficult, and it's a completely different story. – WGH Feb 06 '14 at 12:19
  • Ok, i set "stdout" to None and now everything works just fine. As you said it prints the output on my shell. I would like to redirect it to /dev/null. How can i do it ? – giogix Feb 07 '14 at 08:52
0

Try below

def exec_command(cmd):
    cmd = cmd.split()
    process = subprocess.Popen(cmd, stdout=subprocess.PIPE, preexec_fn=os.setsid)
    pid = process.pid
    print '----------launched process with PID: ', pid 
    return pid
duck
  • 2,483
  • 1
  • 24
  • 34