Shell腳本中信號處理實踐 頂 原

案例
有時需要停止正在運行的腳本,使用Kill -9 <pid>的方式(即發送信號SIGKILL)殺掉進程,有時難免會產生一些垃圾文件,所以需要找出一種方式讓腳本優雅的退出。

解決方案
Shell 腳本可以通過內置的trap命令定製自己的信號處理函數,即捕捉髮送到當前進程的信號並執行自己定義的函數,而不是執行系統默認的函數。注意,SIGKILL 不可捕捉,爲什麼呢?因爲系統總要留下一種結束進程的手段,否則如果全部信號都被捕獲但不即出,那麼這個進程就無法被殺掉了。
trap 命令格式如下:
trap 'command_list' signals
其中,command_list 是一個命令清單,可以包含一個函數,在接收到信號列表中包含的某個信號後運行。而 signals 是將要捕捉的信號的列表。
例如:
捕獲SIGINT, 輸出一條消息後退出,使用
trap 'echo you hit Ctrl-C\, now exiting..; exit' SIGINT

捕獲SIGINT, 什麼也不做,即忽略該信號,使用

trap '' SIGINT

重置SIGINT,即使用系統默認的信號處理函數

trap - SIGINT


本例中,可以捕
獲SIGTERM信號,並指定信號處理函數來實現資源的清理工作,資源清理乾淨後再退出。

實現 


horen@heart$~> cat signal.sh 
#!/bin/bash

trap 'TaskClean; exit' SIGTERM

function TaskOne()
{
   echo "Now do task one..."
   sleep 10
   echo "TaskOne is done"
}

function TaskTwo()
{
   echo "Now do task two..."
   sleep 10
   echo "TaskTwo is done"
}

function TaskClean()
{
   echo "Now do task clean..."
   sleep 2
   echo "TaskClean is done"
}


TaskOne
TaskTwo


運行

horen@heart$~> sh signal.sh 
Now do task one...
Now do task clean...
TaskClean is done

在執行TaskOne時給腳本發送信號SIGTERM,腳本當時在執行“sleep”,sleep結束時轉而去執行信號處理函數。注意,並不是在TaskOne結束後再去執行信號處理函數。 

其他
本例中遇到一個奇怪的問題,暫時沒搞清楚:
如果不捕獲SIGTERM信號,當腳本收到該信號時立即執行系統默認信號處理函數;
如果捕獲SIGTERM信號並指定信號處理函數,當腳本收到該信號時會完成當前的task再執行信號處理函數。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章