陷阱不在shell脚本中工作?

时间:2014-11-11 05:42:43

标签: bash shell unix process

我正在编写OS X上的脚本,需要捕获SIGTERM以便在退出之前杀死一些子进程。为了这个问题,我把它归结为以下最小的例子,由于某种原因,它没有像我期望的那样工作:

#!/bin/sh

function shutdown()
{
  touch foo.txt
  exit 0
}

trap shutdown TERM
su -l myusername -c "sleep 9999"

我在一个终端窗口中运行此脚本,然后切换到另一个,“ps -aef”产生这个:

  502   857   645   0 11:38PM ttys001    0:00.00 /bin/sh ./foo.sh
    0   858   857   0 11:38PM ttys001    0:00.02 su -l myusername -c sleep 9999
  502   859   858   0 11:38PM ttys001    0:00.00 sleep 9999

从第二个窗口开始,我发出“kill -15 857”,但永远不会触发陷阱。脚本在“su”命令上仍然被阻止。

知道为什么吗?我觉得这很简单。

1 个答案:

答案 0 :(得分:13)

bash manual states

  

如果bash正在等待命令完成并收到信号   已经设置了陷阱,陷阱将不会执行,直到   命令完成。

正如gniourf_gniourf所说,这是相对于signals in shells的POSIX规范。

您可以通过捕获例如SIGUSR1代替SIGTERM来检查它;你会看到kill -TERM会再次杀死这个过程。

解决方案是在后台运行命令,然后wait终止它。在这种情况下,trap将起作用。试试这个:

#! /bin/bash

shutdown()
{
    touch foo.txt
    exit 0
}

trap shutdown TERM
su -l myusername -c "sleep 9999" &    # On Ubuntu: sudo su
wait

您将遇到两个问题:su无法在前台询问密码;你必须手动杀死su