鍍金池/ 教程/ Linux/ shell 學(xué)習(xí)五十三天----捕獲信號 trap
shell 學(xué)習(xí)四十一天----列出文件 ls 和 od 命令
shell 學(xué)習(xí)小結(jié)
shell 學(xué)習(xí)第二十八天----case 語句
shell 學(xué)習(xí)四十四天----尋找文件
shell 學(xué)習(xí)三十五天----波浪號展開與通配符
shell 學(xué)習(xí)三十八天----執(zhí)行順序和 eval
shell 學(xué)習(xí)四十八天----文件校驗和匹配
shell 學(xué)習(xí)四十天----awk 的驚人表現(xiàn)
shell 學(xué)習(xí)第十一天----sed 正則的精確控制
shell 學(xué)習(xí)第十七天----awk 命令
shell 學(xué)習(xí)三十九天----內(nèi)建命令
shell 學(xué)習(xí)四十五天----xargs
shell 學(xué)習(xí)三十七天----引用
shell 學(xué)習(xí)第十六天----join 練習(xí)
shell 學(xué)習(xí)第二十四天----提取開頭或結(jié)尾數(shù)行
shell 學(xué)習(xí)第九天----分組
shell 學(xué)習(xí)第五天----基本的 I/O 重定向
shell 學(xué)習(xí)第十五天----使用 cut 選定字段
shell 學(xué)習(xí)四十六天----文件系統(tǒng)的空間信息 df 和 du 命令
shell 學(xué)習(xí)第八天----擴展正則表達式 (ERE)
shell 學(xué)習(xí)第十九天----文本塊排序
shell 學(xué)習(xí)第二十一天----重新格式化段落
shell 學(xué)習(xí)三十六天----命令替換
shell 學(xué)習(xí)第二十天----sort 的其他內(nèi)容以及 uniq 命令
shell 學(xué)習(xí)四十二天----使用 touch 更新文件時間
shell 學(xué)習(xí)五十一天----top 命令查看進程列表
shell 學(xué)習(xí)第一天
shell 學(xué)習(xí)五十四天----進程系統(tǒng)調(diào)用的追蹤 strace
shell 學(xué)習(xí)五十天----查看進程 ps 命令
shell 學(xué)習(xí)第二十七天----退出狀態(tài)和 if 語句
shell 學(xué)習(xí)第二十三天----打印
shell 學(xué)習(xí)三十三天----關(guān)于重定向
shell 學(xué)習(xí)四十九天----進程建立
shell 學(xué)習(xí)第三十天----break,continue,shift,getopts
shell 學(xué)習(xí)五十五天----進程記賬
shell 學(xué)習(xí)總結(jié)一
shell 學(xué)習(xí)第二十六天----變量與算數(shù)
shell 學(xué)習(xí)第二十二天----計算行數(shù), 字數(shù)以及字符數(shù)
shell 學(xué)習(xí)五十八天----/proc 文件系統(tǒng)
shell 學(xué)習(xí)第二十五天----神器的管道符
shell 學(xué)習(xí)第三十二天----read 讀取一行
sheel 學(xué)習(xí)第三天
shell 學(xué)習(xí)----小結(jié)
shell 學(xué)習(xí)第十八天----文本排序
shell 學(xué)習(xí)第三十一天----函數(shù)問題
shell 學(xué)習(xí)第十天----sed 查找與替換
shell 學(xué)習(xí)四十三天----臨時性文件的建立與使用
shell 學(xué)習(xí)四十七天----文件比較 cmp,diff,patch
shell 學(xué)習(xí)三十四天----printf 詳解
shell 學(xué)習(xí)五十七天 ----linux 任務(wù)管理,針對上一講的總結(jié)和擴展
shell 學(xué)習(xí)第六天----小結(jié)
shell 學(xué)習(xí)第十三天----sed 案例分析
shell 學(xué)習(xí)第七天----基礎(chǔ)正則表達式 (BRE)
shell 學(xué)習(xí)第十二天----行與字符串
shell 學(xué)習(xí)小結(jié)四
shell 學(xué)習(xí)第二十九天----循環(huán)
shell 學(xué)習(xí)五十二天----刪除進程 kill 命令
shell 學(xué)習(xí)五十六天----延遲進程調(diào)度
shell 學(xué)習(xí)第四天----華麗的 printf 輸出
shell 學(xué)習(xí)第十五天----join 連接字段
shell 學(xué)習(xí)完結(jié)篇----希望你能看到
shell 學(xué)習(xí)第二天
shell 學(xué)習(xí)五十三天----捕獲信號 trap

shell 學(xué)習(xí)五十三天----捕獲信號 trap

捕捉進程信號

信號是一種進程間的通信機制,它給應(yīng)用程序提供一種異步的軟件中斷,是應(yīng)用程序有機會接受其他程序活終端發(fā)送的命令 (即信號)。應(yīng)用程序收到信號后,有三種處理方式:忽略,默認,捕捉。該進程收到一個信號后,會檢查對該信號的處理機制。如果是 SIG_IGN,就會忽略該信號;如果是 SIG_DFT,則會采用系統(tǒng)默認的處理動作,通常是終止進程或忽略該信號;如果給該信號指定了一個處理函數(shù) (捕捉),則會中斷當(dāng)前進程正在執(zhí)行的任務(wù),轉(zhuǎn)而去執(zhí)行該信號的處理函數(shù),返回后在繼續(xù)執(zhí)行被中斷的任務(wù)。

在有些情況下,我們不希望自己的 shell 腳本在運行時刻被中斷,比如說我們寫的 shell 腳本設(shè)為某一用戶的默認 shell,使這一用戶進入系統(tǒng)后只能做某一項工作,如數(shù)據(jù)庫備份,我們可不希望用戶使用 Ctrl+C 鍵便能進入到 shell 狀態(tài),做我們不希望看到的事情,這便用到了信號處理。

以下是一些常見的信號:

```信號名稱 信號數(shù) 說明 SIGHUP 1 本信號在用戶終端連接 (正?;蚍钦? 結(jié)束時發(fā)出,通常是在終端的控制進程結(jié)束時,通知同一 session 內(nèi)的各個作業(yè),這時它們與控制終端不再關(guān)聯(lián)。登錄 Linux 時,系統(tǒng)會分配給登錄用戶一個終端 (Session)。在這個終端運行的所有程序,包括前臺進程組和后臺進程組,一般都屬于這個 Session。當(dāng)用戶退出 Linux 登錄時,前臺進程組和后臺有對終端輸出的進程將會收到 SIGHUP 信號。這個信號的默認操作為終止進程,因此前臺進程組和后臺有終端輸出的進程就會中止。對于與終端脫離關(guān)系的守護進程,這個信號用于通知它重新讀取配置文件。 SIGINT 2 程序終止 (interrupt) 信號,在用戶鍵入 INTR 字符 (通常是 Ctrl+C) 時發(fā)出 SIGQUIT 3 和 SIGINT 類似,但由 QUIT 字符 (通常是 Ctrl /) 來控制。進程在因收到 SIGQUIT 退出時會產(chǎn)生 core 文件,在這個意義上類似于一個程序錯誤信號。 SIGFPE 8 在發(fā)生致命的算術(shù)運算錯誤時發(fā)出。不僅包括浮點運算錯誤,還包括溢出及除數(shù)為 0 等其它所有的算術(shù)的錯誤。 SIGKILL 9 用來立即結(jié)束程序的運行。本信號不能被阻塞,處理和忽略。 SIGALRM 14 時鐘定時信號,計算的是實際的時間或時鐘時間。alarm 函數(shù)使用該信號 SIGTERM 15 程序結(jié)束 (terminate) 信號,與 SIGKILL 不同的是該信號可以被阻塞和處理。通常用來要求程序自己正常退出。shell 命令 kill 缺省產(chǎn)生這個信號。



**捕獲信號**

當(dāng)按下了 `Ctrl+C` 鍵或 `break` 鍵在終端一個 shell 程序的執(zhí)行過程中,正常程序?qū)⒘⒓唇K止,并返回命令提示符。這可能并使總是可取的,例如,你可能最終留下了一堆臨時文件,將不會清理。

捕獲這些信號是很容易的,`trap` 命令的語法如下:

`\#trap commands signals`

這里的 `commands` 可以是任何有效的 linux 命令,或一個用戶定義的函數(shù),信號可以是任意數(shù)量的信號,你想來捕獲的列表。

- trap 捕捉到信號之后,可以有三種反應(yīng)方式:  
    1. 執(zhí)行一段程序來處理這一信號  
    2. 接受信號的默認操作  
    3. 忽視這一信號  

- trap 對上面三種方式提供了三種基本形式:

    - 第一種形式的 `trap` 命令在 shell 接收到 signal list 清單中數(shù)值相同的信號時,將執(zhí)行雙引號中的命令串。    
  `trap 'commands' signal-list`  
  `trap "commands" signal-list` 
    - 為了恢復(fù)信號的默認操作,使用第二種形式的 trap 命令  
    `trap signal-list`
    - 第三種形式的 trap 命令允許忽視信號  
    `trap " " signal-list`

注意:

1. 對信號 11(段違例) 不能捕捉,因為 shell 本身需要捕捉該信號去進行內(nèi)存的轉(zhuǎn)儲。
2. 在 trap 中可以定義對信號 0 的處理 (實際上沒有這個信號),shell 程序在其終止 (如執(zhí)行 exit 語句) 時發(fā)出該信號。
3. 在捕捉到 `signal-list` 中指定的信號并執(zhí)行完相應(yīng)的命令之后,如果這些命令沒有將 shell 程序終止的話,shell 程序?qū)⒗^續(xù)執(zhí)行收到信號時所執(zhí)行的命令后面的命令,這樣將很容易導(dǎo)致 shell 程序無法終止。另外,在 `trap` 語句中,單引號和雙引號是不同的,當(dāng) shell 程序第一次碰到 `trap` 語句時,將把 `commands` 中的命令掃描一遍。此時若 `commands` 是用單引號括起來的話,那么 shell 不會對 `commands` 中的變量和命令進行替換,否則 `commands` 中的變量和命令將用當(dāng)時具體的值來替換。

**trap 命令用于指定在接收到信號后將要采取的動作。常見的用途是在腳本程序被中斷時完成清理工作。**

測試案例:

按照用戶的要求,我們需要屏蔽的是 `HUP INT QUIT TSTP` 幾個信號。所以,可以運行:
`\#trap “”HUP INT QUIT TSTP`

這個時候,可以試試打開一個持續(xù)的命令,然后中斷其運行,例如:
`\#tail -f /var/log/messages`

接著,試試用 `Ctrl+C` 或 `Ctrl+\` 來中斷試試,該進程是不會退出的。

**恢復(fù)信號** 

如果想恢復(fù)的話,可以用 `Ctrl+Z` 吧進程放到后臺,然后運行:
`\#trap :HUP INT QUIT TSTP`
然后,用 `#ps -ef` 看看其 PID 號,`bg 1` 讓程序繼續(xù)運行,最后用 kill 殺掉即可。

**其他** 

可以試試運行:
`\#trap “echo ‘hello world’” HUP INT QUIT TSTP`
這樣,當(dāng)你運行 `Ctrl+C` 等中斷時,會自動運行 `echo` 命令,結(jié)果就是實現(xiàn) helloworld 字符串。

**引用**  

`\#tail -f /var/log/messages`
注意,這方式并不能屏蔽中斷,按下 `Ctrl+C` 鍵仍然會退出程序,僅會再運行一個額外的命令而已。