[关闭]
@zwh8800 2016-05-24T19:25:19.000000Z 字数 874 阅读 312549

Linux Shell 编程中的 trap 的小坑

blog linux bash shell trap


在 Shell 编程中,为了脚本的健壮性,一般会用到 trap 这个 builtin command。trap 命令类似 c 语言中的 signal 函数,可以注册一个函数,当程序收到信号时执行函数。但是 trap 命令也有一些比较坑的小细节,比如 trap 的执行时机。


在 c 语言中,程序收到信号之后会立即执行 signal 注册的信号处理函数。那么在 shell 程序中呢,信号究竟什么时候被 trap 处理?是像 c 程序一样停下程序立即执行,还是等待当前程序执行之后再执行?

  1. #!/bin/bash
  2. trap 'echo "signal received!"; exit' INT
  3. sleep 100

我们先写一段程序做个实验。在 bash 中执行它,然后按 control + c 发现程序立即停止了,然后打印了 signal received,似乎 trap 是类似 c 程序一样立即处理信号的。但其实是被表面现象蒙骗了。

我们再次执行这个 shell 程序,然后打开另一个 shell,在里面执行 kill -SIGINT xxx 发现 shell 程序并没有退出,等待了 100 秒之后才打印 signal received 退出。

因为第一次在键盘上按 control + c 后,sleep 程序和 shell 程序同属一个进程组,所以也接到了 int 信号退出了,而第二次只有 shell 程序收到信号,所以造成了两者的差异。我第一次也被蒙骗了,傻乎乎的以为 trap 能在 sleep 时也处理信号。

那么问题来了,我们如果需要在 sleep 时处理信号,并且及时退出怎么办呢?国外一篇文章给了例子[1],我就负责搬运一下了。

  1. pid=
  2. trap '[[ $pid ]] && kill $pid' EXIT
  3. sleep 10000 & pid=$!
  4. wait
  5. pid=

利用了 bash 的 builtin 命令 wait。wait 是一个 shell 内部的命令,而不是一个外部程序,所以它没有前面的限制。另外,要记得退出时 kill 掉 sleep 进程,擦好屁股。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注