添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

python程序通过subprocess启动外部程序运行,如果外部程序可以异步执行,可以通过 nohup 方式放到后台执行,避免python程序结束时候,外部程序也被同时kill。

这里需要注意的是, nohup 只是在主进程正常退出情况下禁止 SIGHUP 信号,如果信号是 SIGINT SIGTERM 则子进程也会收到相同信号,这是因为子进程和父进程属于相同的进程组。

要实现父进程退出时子进程不继续执行,有两种方式使用Popen的 preexec_fn 参数:

  • 设置子进程组
  • subprocess.Popen(['nohup', 'my_command'],
                     stdout=open('/dev/null', 'w'),
                     stderr=open('logfile.log', 'a'),
                     preexec_fn=os.setpgrp
    
  • 设置subprocess忽略这些信号:
  • def preexec_function():
        signal.signal(signal.SIGINT, signal.SIG_IGN)
    subprocess.Popen( ... , preexec_fn=preexec_function)
    
    Popen([path] + sys.argv[1:], 
              stdout=DEVNULL, stderr=STDOUT, preexec_fn=ignore_sighup)
    

    nohup ... No such file or directory问题(如果使用参数,需要使用shell)

            cmd = "sh myscript.sh option1"
            p = subprocess.Popen(['nohup', cmd], stdout=open('/dev/null', 'w'),
            stderr=open('myscript.log', 'a'),
            preexec_fn=os.setpgrp )
    

    遇到执行的nohup脚本需要传递参数,但是有如下报错

    nohup: cannot run command `sh myscript.sh option1': No such file or directory
    

    参考 OSError: [Errno 2] No such file or directory while using python subprocess in Django

    对于需要传递参数给脚本的方式,需要设置shell=True

    If passing a single string, either shell must be True or else the string must simply name the program to be executed without specifying any arguments.

    subprocess.call(crop, shell=True)
    
    import shlex
    subprocess.call(shlex.split(crop))
    
            cmd = "sh myscript.sh option1"
            p = subprocess.Popen(['nohup', cmd], shell=True, stdout=open('/dev/null', 'w'),
            stderr=open('myscript.log', 'a'),
            preexec_fn=os.setpgrp )
    

    但是遇到报错

    nohup: missing operand
    Try `nohup --help' for more information.
    
  • Run a program from python, and have it continue to run after the script is killed
  • subprocess gets killed even with nohup
  •