Shell-Script

子 shell 腳本沒有響應發送到前台程序組的終端中斷

  • October 16, 2020

我有一個控制一些衛星腳本的主腳本。當我從終端發送中斷信號時,父母trap捕捉到信號,但孩子沒有,我不知道為什麼。我沒有更改預設終端設置(我沒有在stty任何地方執行)。

這是我的父子腳本和終端輸出:

家長:

#!/bin/sh

./child.sh &

for sig in $(kill -l) ; do
   trap "echo parent:$sig" $sig
done

wait

孩子:

#!/bin/sh

cat < /dev/tty &
PID=$!

for sig in $(kill -l) ; do
   trap "echo child:$sig" $sig
done

wait

終端互動:

[prompt]$ ./parent.sh
^Cparent:INT
cat: stdin: Input/output error

[prompt]$

更新

我在 macOS 和 CentOS 上測試了腳本,出現了上述行為。當我使用預設的 Bourne 兼容 shell 在 FreeBSD 上測試它時,孩子收到的信號是CHLD.

對於由非互動式 shell 非同步執行的命令(實際上是在未啟用作業控制時),在 POSIX 兼容的sh實現中會忽略 SIGINT 和 SIGQUIT。這是一個 POSIX 要求,儘管一些 shell 忽略了它。

另一個 POSIX 要求是,如果一個信號在 shell 啟動時被忽略,你不能取消它,所以你搞砸了。

在這裡,您可以使用沒有那些煩人的“功能”(至少在目前版本中)zsh來代替。sh

在任何情況下,shell 中的信號處理都是最不可靠和便攜的方面之一。您會發現 shell 之間的行為差異很大,並且通常在同一 shell 的不同版本之間。如果您要嘗試做任何不平凡的事情,請為嚴重的頭髮拉扯和頭部抓撓做好準備。

我建議使用不同的語言,您可以更好地控制發生的事情。

此外,我不會盲目處理所有可能的信號,只會處理您期望接收並知道如何處理的信號。例如,擷取 SIGCHLD (shell 本身對此感興趣,因為它的工作是生成程序並處理它們的終止)可能不會做你想做的事情。

引用自:https://unix.stackexchange.com/questions/614774