Linux下trap信号的捕获

trap是一个shell内建命令,它用来在脚本中指定信号如何处理。信号处理在shell编程中非常重要,一般我们会使用信号进行进程间的通信工作。

我们可以使用kill命令发送信号,然后使用trap命令捕获并处理信号。kill命令很多人理解就是杀死进程,殊不知kill除了可以杀死进程还可以做别的。

kill命令本质

kill本质上是在给进程发送特定信号,这个信号可以是告诉进程终止运行、继续运行、暂停运行等等。而进程在收不到这些信号就会执行具体的动作。

在这里插入图片描述
说明:

只有第9种信号(SIGKILL)才可以无条件终止进程,其他信号进程都有权利忽略。 下面是常用的信号:

HUP 1 终端断线
INT 2 中断(同 Ctrl + C)
QUIT 3 退出(同 Ctrl + \)
TERM 15 终止
KILL 9 强制终止
CONT 18 继续(与STOP相反, fg/bg命令)
STOP 19 暂停(同 Ctrl + Z)

上面的信息输入kill -l就显示所有信号的列表。这些信号可以使用数字、英文全称、或者简称表示。但是不同的系统环境对这些表示方式的支持是不一样的,这个具体使用时需要提前测试。推荐使用英文名称,这样兼容性会更好一些。

信号

信号是一种进程间通信机制,它给应用程序提供一种异步的软件中断,使应用程序有机会接受其他程序活终端发送的命令(即信号)。

使用kill命令不指定信号时,默认信号为SIGTERM,该信号默认会终止进程。SIGINT信号等同于使用Ctrl +C组合键,默认会中断进程。

trap.sh

#!/bin/bash

trap "echo 'sorry! I have trapped Ctrl +C'" SIGINT

count=1
while [ $count -le 5 ]
do
	echo "Loop $count"
	sleep 1
	count=$[ $count + 1 ]
done
trap "echo 'Sorry! The trap has been modified.'" SIGINT

count=1
while [ $count -le 5 ]
do
	echo "Loop $count"
	sleep 1
	count=$[ $count + 1 ]
done

echo The end

在这里插入图片描述

而SIGSTOP信号可以暂停一个进程,SIGCONT信号可以恢复暂停的进程继续运行。发送SIGTSTP信号等同于使用Ctrl + Z组合键,也可以通过CONT信号唤醒恢复进程。SIGKILL信号会强制杀死进程。

下面我们通过编写一个死循环来验证这些信号。

#!/bin/bash

while :
do
	echo "signal"
	sleep 1
done

echo "demo"


编译运行:
在这里插入图片描述

因为前面的循环的永远是无限循环,当前命令终端暂时无法使用,我们需要重新开启一个新的命令终端。

查看进程
在这里插入图片描述
这个时候使用命令kill -19 7942,传递暂停信号。

在这里插入图片描述
回到第一个命令终端会发现死循环脚本会被暂停了。

在这里插入图片描述
回到第二个命令终端继续发送恢复信号让继续循环脚本。

在这里插入图片描述
回到第一个终端会发现,脚本继续执行。
在这里插入图片描述

在shell脚本中我们可以通过trap来捕获信号,并捕获信号,并可以自定义需要执行的相应命令,其语法入如下:

在这里插入图片描述

trap命令是专用于捕捉信号的。比如像ctrl+c发送给终端的中断信号等等。在捕捉到信号之后,可以进行一系列的操作。

用法:trap ‘COMMAND’ INT

下面我们接着上面的脚本进行修改,添加trap代码实现捕获信号。

#!/bin/bash

trap 'echo "涓嶄腑鏂瓅鐫$湢.";sleep 3' INT TSTP
trap 'echo 娴嬭瘯;sleep 3' HUP

while :
do
	echo "signal"
	sleep 1
done

echo "demo"

执行脚本后,使用组合键Ctrl +C和Ctrl +Z都不会导致脚本中断和睡眠,反而是在屏幕上显示一条消息后睡眠3秒继续。我们还可以在启动一个命令中断执行 kill -HUP <进程号>

因为无法使用Ctrl+C组合键进行中断操作,所以我们需要查询进程ID后通过TERM信号杀死进程。

在这里插入图片描述

总结

要捕捉发送到您的进程的信号,请使用内置的 trap 命令。在捕捉到信号后,正在执行的当前命令会尝试在 trap 接管之前结束执行。如果该命令为 SIGKILL,那么终止将立即执行。如果忽略某些信号,将执行默认操作。

最后需要说明的是,在Shell脚本中不能捕获所有信号,像TERM、KILL之类的信号是无法被捕获的。

在这里插入图片描述

欢迎关注微信公众号【程序猿编码】,添加本人微信号(17865354792),回复:领取学习资料。或者回复:进入技术交流群。网盘资料有如下:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值