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
...