Linux下Shell信號發送與捕捉

1、Linux信號類型

信號(Signal):信號是在軟件層次上對中斷機制的一種模擬,通過給一個進程發送信號,執行相應的處理函數。

進程可以通過三種方式來響應一個信號:

1)忽略信號,即對信號不做任何處理,其中有兩個信號不能忽略:SIGKILL及SIGSTOP。

2)捕捉信號。

3)執行缺省操作,Linux對每種信號都規定了默認操作。

Linux究竟採用上述三種方式的哪一個來響應信號呢?取決於傳遞給響應的API函數。

Linux支持的信號有:

編號 信號名稱 缺省動作 描述
1 SIGHUP 終止 終止進程,掛起
2 SIGINT 終止 鍵盤輸入中斷命令,一般是CTRL+C
3 SIGQUIT CoreDump 鍵盤輸入退出命令,一般是CTRL+\
4 SIGILL CoreDump 非法指令
5 SIGTRAP CoreDump trap指令發出,一般調試用
6 SIGABRT CoreDump abort(3)發出的終止信號
7 SIGBUS CoreDump 非法地址
8 SIGFPE CoreDump 浮點數異常
9 SIGKILL 終止 立即停止進程,不能捕獲,不能忽略
10 SIGUSR1 終止 用戶自定義信號1,像Nginx就支持USR1信號,用於重載配置,重新打開日誌
11 SIGSEGV CoreDump 無效內存引用
12 SIGUSR2 終止 用戶自定義信號2
13 SIGPIPE 終止 管道不能訪問
14 SIGALRM 終止 時鐘信號,alrm(2)發出的終止信號
15 SIGTERM 終止 終止信號,進程會先關閉正在運行的任務或打開的文件再終止,有時候有的進程在運行任務會忽略此信號。不能捕捉
16 SIGSTKFLT 終止 處理器棧錯誤
17 SIGCHLD 可忽略 子進程結束時,父進程收到的信號
18 SIGCONT 可忽略 讓終止的進程繼續執行
19 SIGSTOP 停止 停止進程,不能忽略,不能捕獲
20 SIGSTP 停止 停止進程,一般是CTRL+Z
21 SIGTTIN 停止 後臺進程從終端讀數據
22 SIGTTOU 停止 後臺進程從終端寫數據
23 SIGURG 可忽略 緊急數組是否到達socket
24 SIGXCPU CoreDump 超出CPU佔用資源限制
25 SIGXFSZ CoreDump 超出文件大小資源限制
26 SIGVTALRM 終止 虛擬時鐘信號,類似於SIGALRM,但計算的是進程佔用的時間
27 SIGPROF 終止 類似與SIGALRM,但計算的是進程佔用CPU的時間
28 SIGWINCH 可忽略 窗口大小改變發出的信號
29 SIGIO 終止 文件描述符準備就緒,可以輸入/輸出操作了
30 SIGPWR 終止 電源失敗
31 SIGSYS CoreDump 非法系統調用

CoreDump(核心轉儲):當程序運行過程中異常退出時,內核把當前程序在內存狀況存儲在一個core文件中,以便調試。執行命令ulimit -c如果是0則沒有開啓,也不會生成core dump文件,可通過ulimit -c unlimited命令臨時開啓core dump功能,只對當前終端環境有效,如果想永久生效,可修改/etc/security/limites.conf文件,添加一行 “* soft core unlimited”

默認生成的core文件保存在可執行文件所在的目錄下,文件名爲core。如果想修改core文件保存路徑,可通過修改內核參數:echo “/tmp/corefile-%e-%p-%t” > /proc/sys/kernel/core_pattern 則文件名格式爲core-命名名-pid-時間戳

Linux支持兩種信號:

一種是標準信號,編號1-31,稱爲非可靠信號(非實時),不支持隊列,信號可能會丟失,比如發送多次相同的信號,進程只能收到一次,如果第一個信號沒有處理完,第二個信號將會丟棄。

另一種是擴展信號,編號32-64,稱爲可靠信號(實時),支持隊列,發多少次進程就可以收到多少次。

信號類型比較多,我們只要瞭解下,記住幾個常用信號就行了,紅色標記的我覺得需要記下。

發送信號一般有兩種情況:

一種是內核檢測到系統事件,比如鍵盤輸入CTRL+C會發送SIGINT信號。

另一種是通過系統調用kill命令來向一個進程發送信號。

2、kill命令

kill命令發送信號給進程。
命令格式:kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... 

kill -l [sigspec]
-s  # 信號名稱
-n  # 信號編號
-l  # 打印編號1-31信號名稱

示例:
給一個進程發送終止信號:
[root@ chenc01 ~]# kill -s SIGTERM pid[root@ chenc01 ~]# kill -n 15 pid[root@ chenc01 ~]# kill -15 pid[root@ chenc01 ~]# kill -TREM pid

3、trap命令

trap命令定義shell腳本在運行時根據接收的信號做相應的處理。
命令格式:trap [-lp] [[arg] signal_spec ...]

-l      # 打印編號1-64編號信號名稱
arg     # 捕獲信號後執行的命令或者函數
signal_spec # 信號名或編號

一般捕捉信號後,做以下幾個動作:
1)清除臨時文件
2)忽略該信號
3)詢問用戶是否終止腳本執行

示例1:按CTRL+C不退出循環
#!/bin/bash
trap "" 2   # 不指定arg就不做任何操作,後面也可以寫多個信號,以空格分隔 
for i in {1..10}; do
  echo $i
  sleep 1
done

[root@ chenc01 ~]# bash a.sh
1
2
3
^C4
5
6
^C7
8
9
10

示例2:循環打印數字,按CTRL+C退出,並打印退出提示

#!/bin/bash
trap "echo 'exit...';exit" 2
for i in {1..10}; do
  echo $i
  sleep 1
done
[root@ chenc01 ~]# bash test.sh
1
2
3
^Cexit...

示例3:讓用戶選擇是否終止循環

#!/bin/bash
trap "func" 2
func() {
  read -p "Terminate the process? (Y/N): " input
  if [ $input == "Y" ]; then
     exit
  fi
}
for i in {1..10}; do
  echo $i
  sleep 1
done
[root@ chenc01 ~]# bash a.sh
1
2
3
^CTerminate the process? (Y/N): Y
[root@ chenc01 ~]# bash a.sh 
1
2
3
^CTerminate the process? (Y/N): N
4
5
6
...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章