8

我正在为应用程序编写一个 bash 包装器。该包装器负责更改用户、运行软件并记录其输出。我还希望它传播 SIGINT 信号。

到目前为止,这是我的代码:

#!/bin/bash
set -e; set -u

function child_of {
    ps --ppid $1 -o "pid" --no-headers | head -n1
}

function handle_int {
    echo "Received SIGINT"
    kill -int $(child_of $SU_PID)
}

su myuser -p -c "bash /opt/loop.sh 2>&1 | tee -i >(logger -t mytag)" &
SU_PID=$!

trap "handle_int" SIGINT

wait $SU_PID
echo "This is the end."

我的问题是,当我向这个包装器发送一个 SIGINT 时,handle_int会被调用,但是脚本结束了,而我希望它继续等待$SU_PID.

有没有办法捕捉 int 信号,做一些事情然后阻止脚本终止?

4

1 回答 1

4

你有一个陷阱:在 Ctrl-C 之后,“这就是结束”。是预期的,但它永远不会出现,因为脚本已过早退出。原因是wait在运行时(出乎意料地)返回非零set -e

根据“man bash”:

如果 bash 正在等待命令完成并接收到已设置陷阱的信号,则在命令完成之前不会执行陷阱。当 bash 通过 wait builtin等待异步命令时,接收到已设置陷阱的信号将导致 wait builtin 立即返回,退出状态大于 128,然后立即执行陷阱。

您应该将wait调用包装起来,set +e以便在等待异步命令时处理捕获的信号后程序可以继续运行。

像这样:

# wait function that handles trapped signal on asynchronous commands.
function safe_async_wait {
  set +e
  wait $1 # returns >128 on asynchronous commands
  set -e
}
#...
safe_async_wait $SU_PID
于 2013-07-09T14:10:47.313 回答