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再执行信号处理函数。

你可能感兴趣的:(shell,信号)