
- Unix/Linux 初學者教程
- Unix/Linux - 首頁
- Unix/Linux - 什麼是Linux?
- Unix/Linux - 入門指南
- Unix/Linux - 檔案管理
- Unix/Linux - 目錄
- Unix/Linux - 檔案許可權
- Unix/Linux - 環境變數
- Unix/Linux - 基本實用程式
- Unix/Linux - 管道與過濾器
- Unix/Linux - 程序
- Unix/Linux - 程序間通訊
- Unix/Linux - vi 編輯器
- Unix/Linux Shell程式設計
- Unix/Linux - Shell指令碼
- Unix/Linux - 什麼是Shell?
- Unix/Linux - 使用變數
- Unix/Linux - 特殊變數
- Unix/Linux - 使用陣列
- Unix/Linux - 基本運算子
- Unix/Linux - 決策語句
- Unix/Linux - Shell迴圈
- Unix/Linux - 迴圈控制
- Unix/Linux - Shell替換
- Unix/Linux - 引用機制
- Unix/Linux - I/O重定向
- Unix/Linux - Shell函式
- Unix/Linux - 手冊頁幫助
- 高階Unix/Linux
- Unix/Linux - 標準I/O流
- Unix/Linux - 檔案連結
- Unix/Linux - 正則表示式
- Unix/Linux - 檔案系統基礎
- Unix/Linux - 使用者管理
- Unix/Linux - 系統性能
- Unix/Linux - 系統日誌
- Unix/Linux - 訊號與陷阱
Unix/Linux - 訊號與陷阱
本章將詳細討論Unix中的訊號和陷阱。
訊號是傳送到程式的軟體中斷,用於指示發生了重要事件。這些事件可以從使用者請求到非法記憶體訪問錯誤不等。某些訊號(例如中斷訊號)指示使用者要求程式執行不在常規控制流程中的操作。
下表列出了您可能在程式中遇到並想要使用的常見訊號:
訊號名稱 | 訊號編號 | 描述 |
---|---|---|
SIGHUP | 1 | 檢測到控制終端上的掛起或控制程序的死亡 |
SIGINT | 2 | 如果使用者傳送中斷訊號 (Ctrl + C),則發出該訊號 |
SIGQUIT | 3 | 如果使用者傳送退出訊號 (Ctrl + \),則發出該訊號 |
SIGFPE | 8 | 如果嘗試執行非法的數學運算,則發出該訊號 |
SIGKILL | 9 | 如果程序收到此訊號,則必須立即退出,並且不會執行任何清理操作 |
SIGALRM | 14 | 鬧鐘訊號(用於計時器) |
SIGTERM | 15 | 軟體終止訊號(預設情況下由kill傳送) |
訊號列表
有一種簡單的方法可以列出系統支援的所有訊號。只需發出 **kill -l** 命令,它將顯示所有受支援的訊號:
$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
Solaris、HP-UX 和 Linux 之間的實際訊號列表有所不同。
預設操作
每個訊號都有一個與其關聯的預設操作。訊號的預設操作是指令碼或程式在收到訊號時執行的操作。
一些可能的預設操作包括:
終止程序。
忽略訊號。
轉儲核心。這將建立一個名為 **core** 的檔案,其中包含程序在收到訊號時記憶體映像。
停止程序。
繼續停止的程序。
傳送訊號
有多種方法可以將訊號傳遞給程式或指令碼。最常見的一種方法是使用者在指令碼執行期間鍵入 **CONTROL-C** 或 **中斷鍵**。
按下 **Ctrl+C** 鍵時,會向指令碼傳送 **SIGINT**,並且根據定義的預設操作,指令碼將終止。
另一種常見的訊號傳遞方法是使用 **kill 命令**,其語法如下:
$ kill -signal pid
這裡 **signal** 是要傳遞的訊號的編號或名稱,**pid** 是應將訊號傳送到的程序 ID。例如:
$ kill -1 1001
上述命令將 HUP 或掛起訊號傳送到程序 ID 為 **1001** 的程式。要向同一程序傳送 kill 訊號,請使用以下命令:
$ kill -9 1001
這將終止程序 ID 為 **1001** 的程序。
捕獲訊號
在shell程式執行期間,當您在終端按下 *Ctrl+C* 或 Break 鍵時,通常該程式會立即終止,並返回您的命令提示符。但這並不總是理想的。例如,您最終可能會留下一些不會被清理的臨時檔案。
捕獲這些訊號非常容易,trap命令的語法如下:
$ trap commands signals
這裡 *command* 可以是任何有效的 Unix 命令,甚至是使用者定義的函式,而 signal 可以是您想要捕獲的任意數量訊號的列表。
在 shell 指令碼中,trap 有兩種常見用途:
- 清理臨時檔案
- 忽略訊號
清理臨時檔案
trap 命令示例如下所示,它演示瞭如何在有人嘗試從終端中止程式時刪除一些檔案然後退出:
$ trap "rm -f $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 2
從執行此 trap 的 shell 程式中的這一點開始,如果程式接收到訊號編號 2,則會自動刪除 **work1$$** 和 **dataout$$** 這兩個檔案。
因此,如果使用者在此 trap 執行後中斷程式的執行,您可以確保這兩個檔案將被清理。 **rm** 後面的 **exit** 命令是必要的,因為如果沒有它,執行將繼續在程式中訊號被接收時中斷的地方繼續。
訊號編號 1 用於 **掛起**。有人故意結束通話線路,或者線路意外斷開。
您可以修改前面的 trap,在這種情況下也可以刪除這兩個指定的檔案,方法是將訊號編號 1 新增到訊號列表中:
$ trap "rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit" 1 2
現在,如果線路結束通話或按下 *Ctrl+C* 鍵,這些檔案將被刪除。
如果指定給 trap 的命令包含多個命令,則必須將它們括在引號中。另請注意,shell 在執行 trap 命令時以及接收到列出的訊號之一時都會掃描命令列。
因此,在前面的示例中,**WORKDIR** 和 **$$** 的值將在執行 trap 命令時被替換。如果您希望此替換在接收到訊號 1 或 2 時發生,您可以將命令放在單引號中:
$ trap 'rm $WORKDIR/work1$$ $WORKDIR/dataout$$; exit' 1 2
忽略訊號
如果列出給 trap 的命令為空,則在接收到指定的訊號時將被忽略。例如,命令:
$ trap '' 2
這指定要忽略中斷訊號。在執行不想被打斷的操作時,您可能希望忽略某些訊號。您可以指定多個要忽略的訊號,如下所示:
$ trap '' 1 2 3 15
請注意,必須指定第一個引數才能忽略訊號,並且它與編寫以下內容不同,後者具有其自身的含義:
$ trap 2
如果忽略訊號,則所有子 shell 也將忽略該訊號。但是,如果指定在收到訊號時要採取的操作,則所有子 shell 仍然會對收到該訊號採取預設操作。
重置陷阱
在您更改了收到訊號後要採取的預設操作後,如果您只是省略第一個引數,則可以使用 trap 再次更改它;所以:
$ trap 1 2
這將收到訊號 1 或 2 後要採取的操作重置為預設值。