Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run a program from python, and have it continue to run after the script is killed

I've tried running things like this:

subprocess.Popen(['nohup', 'my_command'],                  stdout=open('/dev/null', 'w'),                  stderr=open('logfile.log', 'a')) 

This works if the parent script exits gracefully, but if I kill the script (Ctrl-C), all my child processes are killed too. Is there a way to avoid this?

The platforms I care about are OS X and Linux, using Python 2.6 and Python 2.7.

like image 477
James Avatar asked May 15 '11 21:05

James


People also ask

How do I keep a Python program running?

sleep() Function To Run Script repeatedly. So, if you do not want to use the above code and just want to run your script repeatedly then you can use the time. sleep() function. This function allows your script to keep running after sleeping for a certain amount of time.

What is the kill command in Python?

kill() method in Python is used to send specified signal to the process with specified process id. Constants for the specific signals available on the host platform are defined in the signal module. Parameters: pid: An integer value representing process id to which signal is to be sent.

How do you kill a current process in Python?

You can kill a process via its process identifier, pid, via the os. kill() function.


2 Answers

The child process receives the same SIGINT as your parent process because it's in the same process group. You can put the child in its own process group by calling os.setpgrp() in the child process. Popen's preexec_fn argument is useful here:

subprocess.Popen(['nohup', 'my_command'],                  stdout=open('/dev/null', 'w'),                  stderr=open('logfile.log', 'a'),                  preexec_fn=os.setpgrp                  ) 

(preexec_fn is for un*x-oids only. There appears to be a rough equivalent for Windows "creationflags=CREATE_NEW_PROCESS_GROUP", but I've never tried it.)

like image 69
JonMc Avatar answered Sep 19 '22 17:09

JonMc


The usual way to do this on Unix systems is to fork and exit if you're the parent. Have a look at os.fork() .

Here's a function that does the job:

def spawnDaemon(func):     # do the UNIX double-fork magic, see Stevens' "Advanced      # Programming in the UNIX Environment" for details (ISBN 0201563177)     try:          pid = os.fork()          if pid > 0:             # parent process, return and keep running             return     except OSError, e:         print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)          sys.exit(1)      os.setsid()      # do second fork     try:          pid = os.fork()          if pid > 0:             # exit from second parent             sys.exit(0)      except OSError, e:          print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)          sys.exit(1)      # do stuff     func()      # all done     os._exit(os.EX_OK) 
like image 28
edoloughlin Avatar answered Sep 20 '22 17:09

edoloughlin