您的位置:首页 > 运维架构 > Shell

Shell脚本中信号处理实践

2014-07-01 11:56 218 查看
案例

有时需要停止正在运行的脚本,使用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 信号