【问题标题】:How to propagate SIGTERM to children created via subprocess如何将 SIGTERM 传播给通过子进程创建的子进程
【发布时间】:2021-08-21 17:07:15
【问题描述】:

给定以下 Python 脚本:

a.py:

#!/usr/bin/env python3
# a.py
import signal
import subprocess
import os

def main():
    print('Starting process {}'.format(os.getpid()))
    subprocess.check_call('./b.py')

if __name__ == '__main__':
    main()

b.py:

#!/usr/bin/env python3
# b.py
import signal
import time
import os

def cleanup(signum, frame):
    print('Cleaning up...')
    raise RuntimeError("Error")

def main():
    print('Starting process {}'.format(os.getpid()))
    signal.signal(signal.SIGINT, cleanup)
    signal.signal(signal.SIGTERM, cleanup)

    while True:
        print('Hello')
        time.sleep(1)

if __name__ == '__main__':
    main()

如果我执行a.py,然后我通过kill -15 <pid_of_a_py> 杀死它,它会杀死a.py,但b.py 继续运行:

$ ./a.py 
Starting process 119429
Starting process 119430
Hello
Hello
Hello
Hello
Hello
Terminated   // On a separate terminal, I ran "kill -15 119429"
$ Hello
Hello
Hello
Hello

这是为什么呢?如何确保SIGTERMa.py 传播到b.py?还要考虑一个更深的链 a.py -> b.py -> c.py -> d.py ... 我只想为最里面的脚本显式设置错误处理和清理。

【问题讨论】:

    标签: python subprocess sigterm


    【解决方案1】:

    一种解决方案是从a.py 显式抛出SystemExit

    #!/usr/bin/env python3
    # a.py
    import signal
    import subprocess
    import os
    
    
    def cleanup(signum, frame):
        raise SystemExit(signum)
    
    def main():
        signal.signal(signal.SIGINT, cleanup)
        signal.signal(signal.SIGTERM, cleanup)
        print('Starting process {}'.format(os.getpid()))
        subprocess.check_call('./b.py')
    
    if __name__ == '__main__':
        main()
    

    或者,您可以使用Popen 启动进程,并在父进程退出时调用Popen.send_signal 到子进程。

    编辑:

    我已对该主题进行了一些阅读,这是一种预期的行为。 kill -15 <pid> 将信号发送到指定的进程,只有这个,信号不应该被传播。但是,您可以向进程组发送信号,该信号也会杀死所有子进程。语法是kill -15 -<pgid>(注意额外的破折号)。进程组 ID 通常与领导进程 ID 相同。

    【讨论】:

    • 感谢您的回复!我希望我不必那样做,简单地调用 subprocess 并忘记设置信号太容易了。另外,我需要为链 a.py -> b.py -> c.py -> d.py 中的每个步骤复制粘贴所有样板。感觉信号应该默认传递给孩子......
    • 我用额外的解释和更合适的解决方案更新了答案。
    • 很有趣,非常感谢!这正是我一直在寻找的,按预期工作!
    猜你喜欢
    • 2020-07-30
    • 2016-04-03
    • 2013-07-05
    • 2011-03-17
    • 2019-12-26
    • 1970-01-01
    • 2014-06-22
    • 1970-01-01
    • 2013-06-24
    相关资源
    最近更新 更多