15.1-處理信号
Linux使用信号與系統上運作的程序進行通信。
可以使用這些信号控制Shell腳本的運作,隻需要讓shell腳本在接收到來自Linux系統的特定信号時執行指令即可。
1. 常用的Linux信号
編号 | 信号名稱 | 預設操作 | 解釋 | POSIX |
1 | SIGHUP | Terminate | 挂起控制終端或程序 | 是 |
2 | SIGINT | Terminate | 來自鍵盤的中斷 | 是 |
3 | SIGQUIT | Dump | 從鍵盤退出 | 是 |
4 | SIGILL | Dump | 非法指令 | 是 |
5 | SIGTRAP | Dump | 跟蹤的斷點 | 是 |
6 | SIGABRT | Dump | 異常結束 | 是 |
6 | SIGIOT | Dump | 等價于SIGABRT | 是 |
7 | SIGBUS | Dump | 總線錯誤 | 是 |
8 | SIGFPE | Dump | 浮點異常 | 是 |
9 | SIGKILL | Terminate | 強迫程序終止 | 是 |
10 | SIGUSR1 | Terminate | 對程序可用 | 是 |
11 | SIGSEGV | Dump | 無效的記憶體引用 | 是 |
12 | SIGUSR2 | Terminate | 對程序可用 | 是 |
13 | SIGPIPE | Terminate | 向無讀者的管道寫 | 是 |
14 | SIGALRM | Terminate | 實時定時器時鐘 | 是 |
15 | SIGTERM | Terminate | 程序終止 | 是 |
16 | SIGSTKFLT | Terminate | 協處理器棧錯誤 | 是 |
17 | SIGCHLD | Ignore | 子程序停止、結束或在被跟蹤時獲得信号 | 是 |
18 | SIGCONT | Continue | 如果已停止則恢複執行 | 是 |
19 | SIGSTOP | Stop | 停止程序執行 | 是 |
20 | SIGTSTP | Stop | 從tty發出停止程序 | 是 |
21 | SIGTTIN | Stop | 背景程序請求輸入 | 是 |
22 | SIGTTOU | Stop | 背景程序請求輸出 | 是 |
23 | SIGURG | Ignore | 套接字上的緊急條件 | 否 |
24 | SIGXCPU | Dump | 超過CPU時限 | 否 |
25 | SIGXFSZ | Dump | 超過檔案大小的限制 | 否 |
26 | SIGVTALRM | Terminate | 虛拟定時器時鐘 | 否 |
27 | SIGPROF | Terminate | 概況定時器時鐘 | 否 |
28 | SIGWINCH | Ignore | 視窗調整大小 | 否 |
29 | SIGIO | Terminate | I/O現在可能發生 | 否 |
29 | SIGPOLL | Terminate | 等價于SIGIO | 否 |
30 | SIGPWR | Terminate | 電源供給失敗 | 否 |
31 | SIGSYS | Dump | 壞的系統調用 | 否 |
31 | SIGUNUSED | Dump | 等價于SIGSYS | 否 |
- 預設情況下,bash shell會忽略它接收的任何SIGQUIT信号、SIGTERM信号(以防止互動的shell意外終止)。但是,bashshell處理它收到的任何SIGHUP、SIGINT信号。
- 如果bash shell收到一個SIGHUP信号,它會退出。在退出之前,它将SIGHUP信号傳遞給shell啟動的任意程序(如shell腳本)。收到SIGINT信号,shell會立即中斷。Linux核心停止向shell提供CPU 上的處理時間。這種情況下,shell将SIGINT信号傳遞給由shell啟動的人任意程序以通知它們這種情況。
- 預設的shell腳本行為将忽略這些信号,這樣會對腳本運作産生不良影響。為避免這種情況發生,對腳本進行程式設計以識别信号,并執行指令以便腳本為信号結果做好準備。
2. 生成信号
Bashshell可以使用鍵盤上的組合鍵生成兩個基本的Linux信号。如果需要停止或暫停失控的程式,那麼這個功能會被用上。
2.1 中斷程序
使用Ctrl+C組合鍵可以生成SIGINT信号,并将其發送給目前正在shell中運作的任意程序。運作一個通常需要很長時間才能完成的指令并按Ctrl+C組合鍵,可以測試此操作。
Ctrl+C組合鍵不會在螢幕上生成任何輸出,它隻會停止目前在shell中運作的程序。sleep指令在指定的秒數之内暫停操作。
通常,指令提示符在計時器過期之前不會傳回。在計時器過期之前按Ctrl+C組合鍵,可以使sleep指令提前終止。
2.2 暫停程序
Ctrl+Z組合鍵生成SIGSTP信号,可以停止任何在shell中運作的程序。停止程序與終止程序不同,停止程序後程式任然留在記憶體中,能夠從停止的地方繼續運作。
方括号中的數字是shell配置設定的作業編号(jobnumber)。
shell以作業(job)形式引用shell中運作的每個程序,向每個作業配置設定唯一的作業編号。
它向第一個啟動的程序配置設定作業編号1,向第二程序配置設定作業編号2,以此類推。
如果shell會話中有一個停止的作業,在退出shell時bash将發出警告。使用ps指令檢視停止的作業:
在S列(程序狀态),ps指令将已停止作業的狀态顯示為T
如果想在停止作業仍處于活動狀态時退出shell,隻需要再次鍵入exit指令。shell将退出,并終止亭子的作業。還有一種方法是知道停止作業的PID,使用kill指令發送SIGKILL信号來終止它。
2.3 捕獲信号
除了可以使腳本忽略信号之外,還可以在信号出現時捕獲信号和執行其他指令。
trap指令可以指定能夠通過shell腳本監控和攔截的Linux信号。如果腳本收到trap指令中列出的信号,它将保護該信号不被shell處理,并在本地處理它。
trap指令格式:trap commands signals。在trap指令行中,隻需要列出希望shell執行的指令,以及希望捕獲的信号清單(以空格分隔)。指定信号可以通過它們的數值或Linux信号名實作。
當每次檢測到SIGINT和SIGTERM信号時顯示一個簡單的文本消息。如果捕獲到這些信号,在使用者試圖使用bash shell鍵盤Ctrl+C指令停止程式時,腳本将不受影響。每次使用Ctrl+C組合鍵時,腳本執行trap指令中指定的echo語句,而不是忽略信号并允許shell停止腳本。
2.4 捕獲腳本退出
除了在shell腳本中捕獲信号之外,可以在shell腳本退出時捕獲它們。這是一種在shell完成作業時執行指令的便捷方式。要捕獲shell腳本退出,隻需要向trap指令添加EXIT信号。
當腳本到達正常退出點時,就會觸發trap,shell将執行在trap指令行中指定的指令。
如果提前退出腳本,也能夠捕獲EXIT。使用Ctrl+C組合鍵發送SIGINT信号時,腳本退出,但是在腳本退出之前,shell将執行trap指令。
2.5 移除捕獲
要移除捕獲,使用破折号作為指令和想要恢複正常行為的信号清單。
信号捕獲移除後,腳本将忽略信号。但是,如果在移除捕獲之前收到信号,腳本仍将根據trap指令處理該信号。
3. 背景模式下運作腳本
使用ps指令,可以檢視Linux系統上運作的程序。所有程序不在終端螢幕上運作。這就是所謂的背景運作程序。在背景模式中,程序運作時與終端會話STDIN、STDOUT和STDERR無關。
通過指令行界面以背景模式運作shell界面,隻需要在指令後加上一個&符号。将&符号放在指令之後時,它将bashshell與指令相分離,并以獨立的背景程序形式在系統上運作。
顯示的一行類似:[1] 19555,方括号的數字是shell配置設定給背景的作業編号。後面的數字是LInux系統配置設定給程序的PID。所有Linux系統上運作的程序都必須有唯一的PID。
系統顯示這些條目之後,将出現一個新的指令行界面提示符。執行的指令将以後模式安全運作。
這是,可以在提示符處輸出新的指令,但是背景程序仍在運作,任然使用終端螢幕顯示STDOUT和STDERR消息。
背景程序結束時,在終端顯示消息格式:[1]+ Done ./test 這表示作業編号和作業狀态(Done),以及用于啟動該作業的指令。
可以通過指令行提示符同時啟動任何數量的背景作業。每次啟動一個新作業時,Linux系統将配置設定一個新作業編号和一個PID。使用ps指令可以檢視運作的所有腳本。
啟動的每個背景程序都出現在ps指令的運作程序輸出清單中。如果所有程序都在終端會中顯示輸出,那會變成一團糟。