Unix 指南/解釋/訊號
訊號是軟體中斷,通知程序某個條件或事件已經發生。產生訊號的事件示例包括:
- 程序嘗試進行除零運算
- 使用者在終端按下中斷鍵
- 程序使用 kill 命令或 kill 函式向另一個程序傳送訊號
可以使用以下命令顯示所有不同訊號的列表:
$ kill -l
kill 命令還可以用於向其他程序傳送訊號。啟動一個在後臺執行 1000 秒的睡眠程序
$ sleep 1000 & [1] 14936 $ ps PID TTY TIME CMD 14936 pts/7 0:00 sleep 12203 pts/7 0:01 bash
注意,當你執行它時,程序 ID(很可能)會不同。下面的命令列向程序 14936(在本例中)傳送 SIGKILL 訊號
$ kill -KILL 14936 $ ps PID TTY TIME CMD 12203 pts/7 0:01 ksh [1] + Killed sleep 1000 &
收到 SIGKILL 訊號後,sleep 程序將終止。
程序可以以三種不同的方式響應訊號
- 執行預設操作
- 忽略訊號。
- 執行指定函式(稱為訊號處理程式)
程序在收到訊號時執行的預設操作取決於訊號型別。大多數訊號(如 SIGKILL)會導致程序終止。其他訊號,如 SIGQUIT,會導致程序終止並生成核心轉儲
$ sleep 1000 & [1] 14950 $ kill -QUIT 14950 $ ps PID TTY TIME CMD 12203 pts/7 0:01 bash [1] + Quit(coredump) sleep 1000 & $ ls core core
核心檔案可能很大,因此請將其刪除
$ rm core
可以使用 trap 命令捕獲訊號。在檔案 catch_signal.sh 中建立以下 shell 指令碼
#!/bin/bash trap 'echo "GOTCHA!"' INT KILL while : do sleep 10 done
在後臺執行 catch_signal.sh
$ catch_signal.sh & [1] 15053 $ kill -INT 15053 $ GOTCHA!
訊號已捕獲,並且未終止(這是 SIGINT 的預設操作),而是將訊息 "GOTCHA!" 回顯到標準輸出。
但是,某些訊號無法捕獲,例如 SIGKILL
$ kill -KILL 15053 [1] + Killed catch_signal &
執行 catch_signal.sh;在前景中
$ catch_signal
按下中斷鍵(通常是 Ctrl+C)
^CGOTCHA!
現在按下退出鍵
^\catch_signal[3]: 15102 Quit(coredump) $ ls core # will have generated a core file core
使用 nohup 執行的命令在使用者登出時不會終止。
在檔案 dont_hangup.sh 中建立指令碼,並使其可執行
#!/bin/bash
while :
do
date
sleep 100
done
在後臺執行它,前面加上命令 nohup
$ nohup dont_hangup.sh & [1] 15224 Sending output to nohup.out
檢查其執行狀態:id(在本例中為 12203)
$ ps -fu aholt aholt 15224 12203 pts/7 sh ./dont_hangup.sh aholt 15232 15224 pts/7 sleep 100
記錄 "dont_hangup" 的父程序 ID(在本例中為 12203)和終端裝置,然後登出你的會話。
再次登入。可以看到 dont_hangup.sh 仍在執行
$ ps -fu aholt aholt 15224 1 ? 0:00 sh ./dont_hangup.sh aholt 15237 15224 ? 0:00 sleep 100
雖然 "dont_hangup.sh" 仍在執行,但其父程序已更改。父程序的 ID 為 1(而不是之前的 12203),並且不再與終端裝置關聯。使用 nohup 等同於忽略 SIGHUP,即
trap '' HUP