2013-07-08 61 views
4

我正在为应用程序编写bash包装。这个包装器负责更改用户,运行软件并记录其输出。 我也希望它传播SIGINT信号。防止在处理SIGINT后终止bash脚本

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

#!/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信号,做一些事情,然后阻止脚本终止?

+0

如果我明白你的问题:接收后'SIGINT'你希望你的包裹脚本要等到你'su'命令退出之前死亡? – rkyser

+0

@rkyser是的,这正是我想要的。 – mistyrouge

回答

3

你有一个问题:在Ctrl-C之后,“这是结束。”是预料之中的,但它永远不会出现,因为剧本已经过早退出。原因是wait已经(意外地)在set -e下运行时返回非零值。

据“人的bash”:

如果bash等待命令完成并接收针对其陷阱已经设定的信号时,陷阱 不会直到命令完成执行。当bash经由 等待异步命令等待内建,针对其陷阱已设置将导致等待内置到具有退出状态立即返回 一个信号的接收大于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