如何将 SIGTERM 传播给通过子进程创建的子进程
How to propagate SIGTERM to children created via subprocess
给定以下 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
这是为什么?如何确保 SIGTERM
从 a.py
传播到 b.py
?还要考虑更深的链 a.py -> b.py -> c.py -> d.py
...我只想为最里面的脚本显式设置错误处理和清理。
一个解决方案是从 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 相同。
给定以下 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
这是为什么?如何确保 SIGTERM
从 a.py
传播到 b.py
?还要考虑更深的链 a.py -> b.py -> c.py -> d.py
...我只想为最里面的脚本显式设置错误处理和清理。
一个解决方案是从 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 相同。