我正在尝试将进程日志捕获到文件中,同时进程接收 SIGINT 信号进行调试。
timeout -s INT 2 ./myprogram 2>&1 | tee /tmp/1
Run Code Online (Sandbox Code Playgroud)
我发现,当我向管道左侧的进程发送 SIGINT 时,右侧进程也收到 SIGINT,这导致tee退出并且日志丢失。这让我感到惊讶。我编写了以下脚本来重现它:
$ timeout -s INT 1 bash -xc 'trap "echo LEFT SIGINT >&2; sleep 1" INT; sleep infinity' | bash -xc 'trap "echo RIGHT SIGINT" INT; sleep infinity'
+ trap 'echo RIGHT SIGINT' INT
+ sleep infinity
+ trap 'echo LEFT SIGINT >&2; sleep 1' INT
+ sleep infinity
++ echo LEFT SIGINT
++ echo RIGHT SIGINT
RIGHT SIGINT
LEFT SIGINT
++ sleep 1
Run Code Online (Sandbox Code Playgroud)
该脚本在左侧运行,timeout -s INT 1它将在 1 秒后向bash注册INT陷阱处理程序的进程发送 SIGINT 信号,并无限休眠,等待被杀死。右侧也运行 bash,并打开陷阱INT并无限休眠。我的shell是Bash5.2.26。
两个进程都收到了 SIGINT,但只有左侧进程发送了该信号。
为什么正确的进程会收到 SIGINT?
这似乎是一种行为timeout。当我strace运行它(GNU coreutils 8.30 版本)时,我观察到除了向它正在监视的子进程发送信号之外,它还向它自己的整个进程组发送相同的信号。
我还看到它不仅发送请求的信号,还发送SIGCONT,我认为这是为了确保接收者在停止时收到主要信号。
我没有看到任何方法可以阻止timeout这样做,所以如果它给您带来麻烦,那么您需要解决它或避免timeout。