web-dev-qa-db-fra.com

Exécutez un programme à partir de python et continuez à l'exécuter après la mort du script

J'ai essayé de faire des choses comme ça:

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

Cela fonctionne si le script parent se termine correctement, mais si je tue le script (Ctrl-C), tous mes processus enfants sont également tués. Y a-t-il un moyen d'éviter cela?

Les plates-formes dont je me soucie sont OS X et Linux, en utilisant Python 2.6 et Python 2.7.

36
James

La façon habituelle de le faire sur les systèmes Unix est de bifurquer et de quitter si vous êtes le parent. Jetez un œil à os.fork().

Voici une fonction qui fait le travail:

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)
25
edoloughlin

Le processus enfant reçoit le même SIGINT que votre processus parent car il se trouve dans le même groupe de processus. Vous pouvez placer l'enfant dans son propre groupe de processus en appelant os.setpgrp () dans le processus enfant. L'argument preexec_fn de Popen est utile ici:

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

(preexec_fn est uniquement pour un * x-oids. Il semble y avoir un équivalent approximatif pour Windows "creationflags = CREATE_NEW_PROCESS_GROUP", mais je ne l'ai jamais essayé.)

48
JonMc