Запустите программу из python и продолжайте ее запуск после завершения работы скрипта - PullRequest
36 голосов
/ 16 мая 2011

Я пробовал запускать такие вещи, как это:

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

Это работает, если родительский скрипт корректно завершается, но если я убиваю скрипт (Ctrl-C), все мои дочерние процессы тоже будут убиты.Есть ли способ избежать этого?

Мне интересны следующие платформы: OS X и Linux, использующие Python 2.6 и Python 2.7.

Ответы [ 2 ]

47 голосов
/ 05 июня 2013

Дочерний процесс получает тот же SIGINT, что и ваш родительский процесс, потому что он находится в той же группе процессов. Вы можете поместить дочерний элемент в его собственную группу процессов, вызвав os.setpgrp () в дочернем процессе. Здесь используется аргумент popen preexec_fn:

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

(preexec_fn только для un * x-oids. Похоже, что для Windows существует "creationflags = CREATE_NEW_PROCESS_GROUP", но я никогда не пробовал.)

25 голосов
/ 16 мая 2011

Обычный способ сделать это в системах Unix - это разветвиться и выйти, если вы родитель.Посмотрите на os.fork().

Вот функция, которая выполняет эту работу:

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)
...