Shell
為什麼 SIGINT 在發送到其父程序時不會傳播到子程序?
給定一個 shell 程序(例如
sh
)及其子程序(例如cat
),我如何使用 shell 的程序 ID模擬Ctrl
+的行為?C
這是我嘗試過的:
執行
sh
然後cat
:[user@host ~]$ sh sh-4.3$ cat test test
從另一個終端發送
SIGINT
到:cat
[user@host ~]$ kill -SIGINT $PID_OF_CAT
cat
收到信號並終止(如預期)。將信號發送到父程序似乎不起作用。為什麼信號
cat
在發送到其父程序時沒有傳播到sh
?這不起作用:
[user@host ~]$ kill -SIGINT $PID_OF_SH
CTRL
+如何C
工作首先是了解
CTRL
+是如何C
工作的。當您按
CTRL
+C
時,您的終端仿真器會發送一個 ETX 字元(文本結尾/0x03)。TTY 被配置為當它接收到這個字元時,它會向終端的前台程序組發送一個 SIGINT。這個配置可以通過doing
stty -a
和looking來查看intr = ^C;
。POSIX 規範說,當收到 INTR 時,它應該向該終端的前台程序組發送一個 SIGINT。什麼是前台程序組?
那麼,現在的問題是,如何確定前台程序組是什麼?前台程序組只是將接收鍵盤生成的任何信號(SIGTSTP、SIGINT 等)的程序組。
確定程序組 ID 的最簡單方法是使用
ps
:ps ax -O tpgid
第二列將是程序組 ID。
如何向程序組發送信號?
現在我們知道程序組 ID 是什麼,我們需要模擬向整個組發送信號的 POSIX 行為。
這可以通過在組 ID 前面
kill
放置一個來完成。 例如,如果您的程序組 ID 是 1234,您將使用:-
kill -INT -1234
使用終端號模擬
CTRL
+ 。C
因此,以上內容涵蓋瞭如何將
CTRL
+模擬C
為手動過程。但是,如果您知道 TTY 號碼,並且想為該終端模擬CTRL
+怎麼辦?C
這變得非常容易。
假設
$tty
是您要定位的終端(您可以通過tty | sed 's#^/dev/##'
在終端中執行來獲得它)。kill -INT -$(ps h -t $tty -o tpgid | uniq)
這將向前台程序組發送一個 SIGINT
$tty
。