【问题标题】:Python Script called executed from bash script not handling signals从 bash 脚本调用的 Python 脚本不处理信号
【发布时间】:2019-07-30 15:16:29
【问题描述】:

问题:从命令行执行 python 脚本时,它会按预期捕获和处理 SIGTERM 信号。但是,如果脚本由 bash 脚本调用,然后 bash 脚本将信号发送到 python 脚本,则它不会按预期处理 SIGTERM 信号。

有问题的python脚本非常简单:它等待一个SIGTERM,然后等待几秒钟然后退出。

    #!/usr/bin/env python3

    import sys
    import signal
    import time


    # signal handler
    def sigterm_handler(signal, frame):
        time.sleep(5)
        print("dying")
        sys.exit()

    # register the signal handler
    signal.signal(signal.SIGTERM, sigterm_handler)


    while True:
        time.sleep(1)

如果这是直接调用然后从命令行发送的信号 即

> ./sigterm_tester.py &
> kill -15 <PID>

信号处理正常执行(等待 5 秒,将“垂死”发布到标准输出,然后退出)

但是,如果它是从 bash 脚本调用的,它似乎不再捕获 SIGTERM 而是立即退出。 这个简单的 bash 脚本执行 python 脚本,然后杀死它的子脚本(python 脚本)。但是,终止立即发生,而不是在 5 秒延迟后发生,并且没有将“垂死”打印到 stdout(或当我尝试 stdout 重定向时打印到文件)。


    #!/bin/bash

    ./sigterm_tester.py &

    child=$(pgrep -P $$)

    kill -15 $child

    while true;
    do
        sleep 1
    done

一些附加信息:我还用 sh 和 bash 对此进行了测试,并且发生了相同的行为。此外,我已经对此进行了测试,并在 MacOS 环境和 Linux 环境中获得了相同的行为。我也用python2和python3测试过。

我的问题是为什么行为似乎取决于程序的调用方式不同,有没有办法确保即使从 bash 脚本调用 python 程序也能正确处理信号?

【问题讨论】:

    标签: python bash shell


    【解决方案1】:

    求和@Matt Walck cmets。在 bash 脚本中,您在调用它后立即杀死了 python 进程,这可能没有足够的时间在 sigterm 信号上注册。在 spawn 和 kill 命令之间添加 sleep 命令将支持该理论。

    #!/bin/bash
    
    ./sigterm_tester.py &
    
    child=$(pgrep -P $$)
    
    #DEBUGONLY
    sleep 2
    
    kill -15 $child
    
    while true;
    do
            sleep 1
    done
    

    【讨论】:

    • 这似乎有效。当您说它似乎正在杀死正在调用该进程的进程时,该进程是什么?在原始脚本中,我认为可能是这种情况,所以我检查了进程是否有任何子进程,但它没有子进程,所以我认为它必须是 python 程序。
    • 更有趣的是,我修改了程序以打印出 $(pgrep -P $$) 和 $(ps -ef | grep sigterm_tester.py | awk {'print $2'} 返回的内容) 并且它们是相同的(减去 grep 命令的附加 PID)。所以现在我很困惑为什么这会返回不同的结果
    • 用一些印刷品更新了答案,希望能解释正在发生的事情。
    • 所以我只是做了一些进一步的测试,实际上并不是杀死调用进程的问题:这是一个很好的老式竞争条件。原始过程太快并杀死它。但是,您的所有重定向进程似乎已经给了另一个进程足够的时间来加载库并注册信号处理程序。如果您在有 echo $child 的位置下添加“echo $(ps -ef | grep sigterm_tester | awk {'print $2'})”,或者如果您在我在原始文件中杀死孩子之前添加 sleep 1,您可以看到这一点脚本
    • 如果您想相应地编辑您的答案,我很高兴接受您的回答,您在发现问题方面非常宝贵。几个小时以来,我一直在努力解决这个问题。或者我可以编辑它,无论哪种方式,非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 2012-07-23
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    相关资源
    最近更新 更多