迅速学会linux信号捕获

阿里云教程10小时前发布 华亦
2 0 0

前几天看脚本看到trap这个命令的时候想起来一件趣事。记得刚开始学linux的时候,几个新手建了一个学习群每天交流学习心得,也会炫耀一下自己刚学到的命令。有一天一个群友发了个脚本文件,说自己这里没法执行,让我们试试能不能执行。没看脚本就直接在电脑上执行了,结果每隔五秒会显示一句“You are pig”,使用ctrl+c没反应,新开终端使用 kill PID 也无法终止,最后使用 kill -9 PID 才杀死。。。

这个脚本是我第一次接触trap,借此机会纪念一下当年共同学习的美好日子。先贴脚本(可以用 kill -9 PID 终止,呵呵。。。)

#!/bin/bash

trap “” 2 9 15
while (true)
do
echo “You are pig”
sleep 5
done

该脚本运行后使用 ctrl+c,重开终端使用 kill PID 是无法停止的,只能使用 kill -9 PID 杀死进程(有朋友会疑问 9 不是也被捕捉了吗,为什么可以终止?请往下看)。无法停止的缘由是trap的存在,下面简单介绍一下trap命令的用法:

1、语法格式:trap [选项] [COMMAND] [SIGNAL]

2、选项:
-l:列出所有的信号(与 kill -l 输出一样)
-p:列出所有使用trap设置过的信号

3、COMMAND:
command/shell:捕捉到指定信号后执行的动作
“”:屏蔽指定信号(什么也不干)
-:恢复信号原来的定义(可省略,使用 trap -p 无法列出)
::恢复信号原来的定义(使用 trap -p 可以列出)

4、SIGNAL:指定的信号,可以是 trap -l 列出的信号,也可以是 DEBUG, RETURN, EXIT,常用信号有:
SIGINT:即 ctrl+c,SIGINT, INT, 2, sigint, int 均合法
DEBUG:从设置位置开始任意命令前执行(包括其他 trap 命令),如为函数仅在函数的第一条命令前执行一次
RETURN:在函数返回时,或者.和source执行其他脚本返回时被捕捉
EXIT:在shell退出前执行捕获,也可以写为 0
* 信号比较灵活,可以是数字,信号名(信号名可以省略 SIG,且大小写不敏感)
* 可接收多个信号,使用空格隔开
* SIGKILL(9), SIGSTOP(19)信号直接作用于内核,无法被捕捉(kill -9 可以杀死进程的缘由

5、常用命令举例:
trap -l:列出所有的信号
trap -p:列出所有使用trap设置过的信号
trap “” 2 15:屏蔽 INT 和 TERM 信号
trap – INT:把 INT 信号恢复原来的作用(- 可以省略)

6、shell 中使用 trap 捕获DEBUG, EXIT, RETURN:

#!/bin/bash

trap “This is debug” DEBUG
trap “This is exit” EXIT

func () {
trap “This is return” RETURN
echo “This is func”
}
echo “Hello world”
func
trap “This is debug1” DEBUG

输出及说明:
This is debug # 执行 trap “This is exit” EXIT 前捕获
This is debug # 执行 echo “Hello world” 前捕获
Hello world
This is debug # 执行程序 func 的第一条命令前捕获
This is func
This is return # 子程序返回捕获为 RETURN
This is debug # 执行 trap “This is debug1” DEBUG 前捕获
This is debug1 # 捕获到捕获 EXIT 输出的输出
This is exit # 捕获到 EXIT 的输出

7、trap使用注意事项:
* SIGKILL 和 SIGSTOP 直接作用于内核,无法使用 trap 捕捉
* 对于同一个信号,以最后一次 trap 为准
* trap 只在本进程有效,其子进程不会继承 trap 设置
* 在程序中,trap 全局有效

文中找脚本的PID,可以使用 pidof -x, pgrep, ps, pstree 等命令获取。(pidof 需要使用 -x 选项哦。。。)

© 版权声明

相关文章

暂无评论

none
暂无评论...