控制腳本之信號控制作業
①信號基礎
>>>Linux系統上通過Linux信號可以實現對腳本的控制
>>>bash shell會忽略SIGQUIT(3)和SIGTERM(15)的信號,會處理SIGHUP(1)和SIGINT(2)的信號
Linux常見的系統信號
常見信號 |
值 |
描述 |
1 |
SIGHUP |
掛起進程 |
2 |
SIGINT |
終止進程 |
3 |
SIGQUIT |
停止進程 |
9 |
SIGKILL |
無條件終止進程 |
15 |
SIGTERM |
可能的話終止進程 |
17 |
SIGSTOP |
無條件停止進程但不終止進程 |
18 |
SIGSTP |
停止或者暫停進程,但不終止進程 |
19 |
SIGCONT |
繼續停止的進程 |
說明:
當bash shell收到SIGHUP信號時,bash shell會退出,但在退出之前,bash shell會將SIGHUP信號傳給shell啓動的所有進程(包括shell腳本)
可以通過SIGINT信號去終端bash shell,當bash shell收到SIGINT信號時,會通知shell啓動的所有進程,SIGINT信號意味着Linux內核會停止將CPU處理時間分配給收到該信號的shell
②產生信號
>>>bash shell允許鍵盤上的按鍵組合產生基本的Linux信號
產生信號分類
按鍵組合 |
描述 |
Ctrl+C |
發送SIGINT信號到當前正在運行的作業,讓作業終止 |
Ctrl+Z |
發送SIGSTP信號,將一個正在前臺執行的任務進程放到後臺運行,並將任務進程掛起,此時狀態爲STOP |
案例
[bei@localhost test]$ sleep 100
^Z
[1]+ Stopped sleep 100
[bei@localhost test]$ jobs
[1]+ Stopped sleep 100
#停止多個進程後
[beihuatao@localhost ~]$ jobs
[1] Stopped sleep 100
[2] Stopped sleep 100
[3]- Stopped sleep 100 : - 表示信號下一個處理的進程
[4]+ Stopped sleep 100 : + 表示信號處理的進程
說明:
bash shell會將shell中運行的每個進程稱爲作業(job)
bash shell會爲每個作業分配一個唯一的作業號,方括號中[ ]的數字表示的是shell分配的作業號
Stopped表示作業在後臺的狀態爲停止
可以使用ps命令查看已停止的作業,找到對應的PID,可以使用向作業發送SIGKILL信號的方式終止作業
案例
[bei@localhost test]$ ps -ef | grep "bei"
root 41490 41466 0 18:43 pts/1 00:00:00 su - bei
bei 41491 41490 0 18:43 pts/1 00:00:00 -bash
root 42614 42231 0 20:13 pts/2 00:00:00 su - bei
bei 42615 42614 0 20:13 pts/2 00:00:00 -bash
bei 42648 42615 0 20:14 pts/2 00:00:00 sleep 100
bei 42781 42615 0 20:36 pts/2 00:00:00 ps -ef
bei 42782 42615 0 20:36 pts/2 00:00:00 grep bei
[bei@localhost test]$ kill -9 42648
[bei@localhost test]$ ps -ef | grep "bei"
root 41490 41466 0 18:43 pts/1 00:00:00 su - bei
bei 41491 41490 0 18:43 pts/1 00:00:00 -bash
root 42614 42231 0 20:13 pts/2 00:00:00 su - bei
bei 42615 42614 0 20:13 pts/2 00:00:00 -bash
bei 42783 42615 0 20:36 pts/2 00:00:00 ps -ef
bei 42784 42615 0 20:36 pts/2 00:00:00 grep bei
[1]+ Killed sleep 100
說明:ps命令的第二列爲PID,輸入kill -9 PID即可終止進程
③捕捉信號
>>>默認情況下,shell腳本是不會去處理bash shell發送過來的信號
>>>可以使用trap命令指定shell腳本可以捕捉哪些信號
>>>當腳本收到了trap命令中列出的信號,trap命令會組織信號被shell處理,而在本地處理
例:trap命令可以去監聽SIGSTP信號,當腳本收到SIGSTP信號時,trap命令就會捕捉這個信號,讓腳本不受影響
trap命令基本格式:
trap commands signals
>>>信號以空格分隔開,可以用數值,也可以用名稱
>>>commands表示當捕捉到信號,想要執行的shell命令
>>>命令用引號引起來,每次阻止到指定信號,都會執行命令
案例
[bei@localhost test]$ cat signal.sh
#!/bin/bash
trap "echo 'sorry,the signal[Ctrl+C] has been trapped.'" SIGINT
count=1
while [ $count -le 5 ]
do
echo "sleep $count"
sleep $count
count=$[ $count + 1 ]
done
echo "end"
[bei@localhost test]$ bash signal.sh
sleep 1
sleep 2
sleep 3
^Csorry,the signal[Ctrl+C] has been trapped.
sleep 4
^Csorry,the signal[Ctrl+C] has been trapped.
sleep 5
end
說明:
此案例中,使用trap命令去捕捉SIGINT信號,若SIGINT信號被捕捉到,無法終止腳本,而會顯示一行文本
④運行模式
>>>大部分情況下,我們執行腳本是在命令行上直接運行,此時我們無法同時使用命令行進行其他操作,只有等待腳本執行結束
>>>當腳本運行時間過長時,如果需要使用命令行做其他事情,我們可以將腳本放入到後臺去運行
後臺運行腳本(與終端關聯)
>>>可以使用 bash scripts & 這種方式將scripts腳本放入到後臺運行
>>>腳本中的輸出(標準輸出或標準錯誤輸出)都會打印在屏幕上
>>>每個後臺進程都會綁定到該終端的繪畫的終端上(pts/0),當終端會話進程退出,會終止該終端後臺的進程
案例
[bei@localhost test]$ cat signal.sh
#!/bin/bash
count=1
while [ $count -le 5 ]
do
echo "sleep $count"
sleep $count
count=$[ $count + 1 ]
done
echo "end"
[bei@localhost test]$ bash signal.sh &
[1] 43055
[bei@localhost test]$ sleep 1
sleep 2
sleep 3
sleep 4
[bei@localhost test]$
[bei@localhost test]$ ls -al
total 100
drwxrwxr-x. 2 bei bei 4096 Sep 25 21:10 .
drwxr-xr-x. 6 bei bei 4096 Sep 16 19:51 ..
-rw-rw-rw-. 1 bei bei 120 Sep 25 21:10 signal.sh
[bei@localhost test]$ sleep 5
pwd
/home/bei/linux/test
[bei@localhost test]$ end
[1]+ Done bash signal.sh
說明:
當腳本放入到後臺執行時會有一個輸出,如[1] 43055,
其中[1]表示的是當前bash shell給這個作業分配的作業號,4305表式 分配給腳本的進程號PID
當腳本結束後,會有一個輸出,如 [1]+ Done bash signal.sh 表示腳本已結束
非控制檯下運行腳本(與終端不關聯)
>>>需求:即使終端會話進程退出,在後臺運行的腳本也不會退出,一直運行直到腳本自身運行完成
>>>可以使用nohup命令:nohup bash scripts &
>>>不會有標準輸出和標準錯誤輸出,而將輸出追加式重定向到nohup.out 文件中(輸出追加到此文件中,不刪除原來的內容)
>>>nohup bash scripts> myout.file 2>&1 & #重定向到指定文件
案例
[bei@localhost test]$ cat signal.sh
#!/bin/bash
count=1
while [ $count -le 5 ]
do
echo "sleep $count"
sleep $count
count=$[ $count + 1 ]
done
echo "end"
[bei@localhost test]$ nohup bash signal.sh &
[1] 43155
[bei@localhost test]$ nohup: ignoring input and appending output to `nohup.out'
[bei@localhost test]$
[bei@localhost test]$ jobs
[1]+ Running nohup bash signal.sh &
[bei@localhost test]$
[1]+ Done nohup bash signal.sh
[bei@localhost test]$ ls -al ./nohup.out
-rw-------. 1 bei bei 88 Sep 25 21:26 ./nohup.out
[bei@localhost test]$ cat ./nohup.out
sleep 1
sleep 2
sleep 3
sleep 4
sleep 5
end
⑤作業控制
>>>作業控制:啓動、停止、無條件終止以及恢復作業等功能
作業控制只查看作業
>>>可以使用jobs命令查看後臺進程
[bei@localhost test]$ bash signal.sh
^Z
[1]+ Stopped bash signal.sh
[bei@localhost test]$ bash signal.sh &
[2] 43611
[bei@localhost test]$ jobs
[1]+ Stopped bash signal.sh
[2]- Running bash signal.sh &
說明:
>>>對於作業[1]使用Ctrl+z掛起,在jobs中顯示Stopped表示作業已經暫時掛起
>>>對於作業[2],使用在執行腳本命令後面加上&符號,使它在後臺運行,在jobs中顯示Running表示作業正在運行中
>>>作業號的右邊有加號"+"和減號"-",帶加號的作業表示默認作業,表示使用作業控制命令時,未在命令行上指定作業號則默認操作的是帶加號的作業;帶減號的作業是帶加號的作業的備胎,比如kill掉作業[1],原來帶減號的作業[2]的減號就變成了加號
jobs命令相關選項說明
參數 |
描述 |
-l |
列出進程的PID和對應的作業號 |
-n |
只列出上次shell發出的通知後改變狀態的作業 |
-p |
只列出作業的PID |
-r |
列出處於運行狀態的作業 |
-s |
列出處於暫停狀態的作業 |
批量kill後臺的正在運行的所有進程
a= `jobs -p` #將所有進程的PID賦予給變量a
for i in $a;do kill $i;done #如果想要kill後臺所有進程,包括stopped的進程,使用-9參數,無條件終止進程(慎用)
終止後臺指定作業號的作業:kill %number (建議用作業號的方式kill,不用PID的方式)
[bei@localhost test]$ jobs
[1]- Stopped bash signal.sh
[2]+ Stopped bash signal.sh
[3] Running bash signal.sh &
[bei@localhost test]$ kill %3
[bei@localhost test]$ jobs
[1]- Stopped bash signal.sh
[2]+ Stopped bash signal.sh
[3] Terminated bash signal.sh
注意:可以輸入命令 kill %
不指定作業號,則kill的作業是帶加號的作業
作業控制之重啓停止的作業
>>>fg命令:將後臺進程調至前臺運行
fg number (如果不加number,默認操作的是有+的作業)
案例
[bei@localhost test]$ cat signal.sh
#!/bin/bash
count=1
while [ $count -le 5 ]
do
echo "$count second sleep"
sleep 1
count=$[ $count + 1 ]
done
echo "End"
[bei@localhost test]$ bash signal.sh
1 second sleep
2 second sleep
3 second sleep
^Z
[1]+ Stopped bash signal.sh
[bei@localhost test]$ fg 1
bash signal.sh
4 second sleep
5 second sleep
End
>>>bg命令:將掛起的進程在後臺啓動爲運行狀態:
bg number (如果不加number,默認操作的是有+的作業 )
案例
[bei@localhost test]$ bash signal.sh
1 second sleep
^Z
[1]+ Stopped bash signal.sh
[bei@localhost test]$ bg 1
[1]+ bash signal.sh &
[bei@localhost test]$ 2 second sleep
3 second sleep
jobs
[1]+ Running bash signal.sh & #輸入jobs查看到作業正在後臺運行,輸出在屏幕上
[bei@localhost test]$ 4 second sleep
5 second sleep
End
[1]+ Done bash signal.sh
說明:
>>>以上內容是本人學習的總結
>>>如還有錯誤,請留言,指正
>>>亦可分享自己的想法,互相學習