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

shell trap命令的一些特殊注意的地方

2017-02-08 11:35 609 查看
实验1

有下面的bash代码,脚本名signal.bash。

#!/bin/bash
trap 'echo INTRRUPTED BY SIGNAL INT' INT
seconds0=$(date +%s)
sleep 60s
seconds1=$(date +%s)
echo "sleeped seconds : $((seconds1 - seconds0))s"
chenglin@ubuntu-chenglin:~/shellscript/other$ time ./signal.bash
^CINTRRUPTED BY SIGNAL INT
sleeped seconds : 22s

real	0m21.427s
user	0m0.000s
sys	0m0.004s


ctrl+c后能立即停止signal.bash脚本的运行。

分析: 前台运行signal.bash脚本,其所有子程序(外部命令)和signal.bash程序在同一个进程组。而ctrl+c会发送给前台进程组所有进程INT信号。signal.bash运行后会产生两个进程,一个是signal.bash程序本身,另外一个是sleep程序(sleep是外部命令)。而sleep和signal.bash在同一个前台进程组,所以ctrl+c时,sleep程序由于处于
TASK_INTERRUPTIBLE
状态(ps -axu可以看到其状态是S+)。所以会被信号INT唤醒,信号action为终止进程,自然父进程继续运行。得出运行,直到sleep被信号INT中断的睡眠时间。

实验2

现在做另外一个实验:

开两个终端,第一个终端里面运行time ./signal.bash。迅速(60s内)在第二个终端里面运行如下:

chenglin@ubuntu-chenglin:~/shellscript/powerConsumption-net$ pgrep -f signal.bash -l
25700 signal.bash
chenglin@ubuntu-chenglin:~/shellscript/powerConsumption-net$ kill -INT 25700
发现第一个终端中打印如下:

chenglin@ubuntu-chenglin:~/shellscript/other$ time ./signal.bash
INTRRUPTED BY SIGNAL INT
sleeped seconds : 60s

real 1m0.013s
user 0m0.004s
sys 0m0.004s

第二个终端不能立即停止第一个终端中signal.bash的运行。
分析: 在第二个终端是,信号INT是指定发送给signal.bash的,而不是sleep的,所以sleep没有接收到INT信号,而继续睡眠,直到指定的时间60s后,当60s后,sleep返回。主程序signal.bash此时才会处理信号。打印INTRRUPTED BY SIGNAL INT,说明处理了信号INT。

实验3

现在做第三个实验:

开两个终端,第一个终端里面运行time ./signal.bash。迅速(60s内)在第二个终端里面运行如下:

chenglin@ubuntu-chenglin:~/shellscript/powerConsumption-net$ pgrep -f sleep -l
25708 sleep
chenglin@ubuntu-chenglin:~/shellscript/powerConsumption-net$ kill -INT 25708
chenglin@ubuntu-chenglin:~/shellscript/powerConsumption-net$ 发现第一个终端打印如下:
chenglin@ubuntu-chenglin:~/shellscript/other$ time ./signal.bash
sleeped seconds : 16s

real 0m15.915s
user 0m0.000s
sys 0m0.008s

分析:和实验2不同,这里是直接对sleep发送INT信号,可以直接唤醒sleep进程,并终止。但是注意到signal.bash并没有打印INTRRUPTED BY SIGNAL INT,因为信号是发给sleep进程,而不是signal.bash进程的。所以sgnal.bash进程无需处理INT信号。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: