無痕的碎碎念

Shell Script - Trap

原创文章,转载请标明出处:無痕的碎碎念
本文链接地址:Shell Script - Trap

最近写 Shell 脚本的时候发现一个需求:

  • 有一条(或组)命令不希望被打断执行,或者不能被打断执行。

举个例子来说,有一个时间比较长的追加写入操作,中间在执行过程中如果中断的话会很麻烦,要清理文件或者判断写到什么位置了。这时候如果有个方法能保证这个操作完成,不会因为手抖按了 C-c 被中断掉。
在不存在的网站 Google 上找了一下,在 Shell 中有一个捕获系统信号的命令 trap

用法

trap command signals
trap 在捕获到 signals 中定义的信号之后,会执行 command 指定的命令。

注意事项

虽然提供了这么一个命令来捕获系统信号,但是在实际使用的时候会发现很多信号捕获不了:

  • SIGSTOP
  • SIGKILL

此外,处于 Shell 的交互模式的时候,以下信号也捕获不了:

  • SIGTTIN
  • SIGTTOU
  • SIGTSTP

解决问题

上面说了这么多,然而并没有解决问题,虽然捕获了信号,但是还是会打断当前进行的操作。
trap 在捕获到信号,执行指定的 command 的时候,会忽略掉其他的信号(当然 SIGKILLSIGSTOP 这种没办法)。利用这一点,把需要保证完成的操作作为指定的 command ,然后在设置捕获信号之后马上对自己发出一个可以捕获的信号就可以了。

1
2
3
4
assert() {
trap '$@; trap - SIGINT' SIGINT
kill -INT $$
}

只要把需要执行的命令作为 assert 函数的参数传入就好了。

还有个问题

这个方法对 C-z 是无效的,不过可以利用它来结束掉这条指令。毕竟执行到一半发现什么奇怪的问题,需要结束这种情况还是难免的。