跳轉到內容

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
華夏公益教科書