我真的很努力为这个问题找到一个更好的标题。我愿意接受建议。
我编写了一个 bash 脚本,EXIT
如果收到该信号,它会捕获并调用一个函数。当调用的文件stop
存在时,它会调用相同的函数。这里是:
#!/bin/bash
TAIL_PID=0
CAT_PID=0
DEVICE=/dev/ttyACM0
WDIR=plasma
LOGFILE=$WDIR/$(date +%Y%m%d_%H%M%S.log)
CMDFILE=$WDIR/toDevice
function kill_tail
{
if [ $TAIL_PID -ne 0 ]
then
kill $TAIL_PID
TAIL_PID=0
echo "killed tail"
fi
}
function kill_cat
{
if [ $CAT_PID -ne 0 ]
then
kill $CAT_PID
CAT_PID=0
echo "killed cat"
fi
}
function on_die
{
echo 't 0' >> $DEVICE
kill_tail
kill_cat
echo "stopped logging"
}
trap on_die EXIT
# mount plasma oven directory if it is not already mounted
mountpoint -q $WDIR || sshfs user@server:plasma $WDIR
# see if device is available/wait for device
while [ ! -c $DEVICE ]
do
sleep 1
done
echo "Found controller"
# stop output, remove start and stop files
echo 't 0' >> $DEVICE
rm $WDIR/start $WDIR/stop
# outer loop
while [ 1 ]
do
while [ ! -f $WDIR/start ]
do
sleep 1
done
rm $WDIR/start
# stop output
echo 't 0' >> $DEVICE
# pass commands to device
# but clear existing commands first
> $CMDFILE
tail -f $CMDFILE > $DEVICE &
TAIL_PID=$!
echo "tail PID = " $TAIL_PID
# start logging
cat $DEVICE >> $LOGFILE &
CAT_PID=$!
echo "cat PID = " $CAT_PID
# start output
echo 't 1000' >> $DEVICE
echo "started logging to " $LOGFILE
while [ ! -f $WDIR/stop ]
do
sleep 1
done
rm $WDIR/stop
on_die
done # end of outer loop
当我运行此脚本时, after touch start
,它会根据 ICTRL-C
或touch stop
.这是 ing 后的输出CTRL-C
:
killed tail
killed cat
stopped logging
这是之后的输出touch stop
:
killed tail
killed cat
stopped logging
./mountPlasma: line 93: 21200 Terminated tail -f $CMDFILE > $DEVICE
./mountPlasma: line 93: 21201 Terminated cat $DEVICE >> $LOGFILE
为什么?调用相同的函数,我希望两次调用都有相同的输出on_die
。输出表明两条额外的消息是在第 93 行发出的done # end of outer loop
(行号与上面的代码不完全匹配,因为我必须为这篇文章删除几行)。
由于我对 bash 非常缺乏经验,我不知道这是否有任何副作用。tail
和都cat
如预期被杀死了。
答案1
当您点击 时Ctrl-C
,正在运行的脚本会获取 SIGINT 并将其传播给它的子级,而在“常规”退出时,它将发送默认的 SIGTERM (来自使用 注册的函数EXIT
)。
Ctrl-C
也就是说,和停止条件之间有很大的区别。虽然在这两种情况下都会调用退出处理程序函数,但实际事件完全不同。在 SIGINT 的情况下,子进程被该进程杀死(或者至少可能被杀死)和解释脚本的 shell 没有太多机会报告此状态更改。在另一种情况下它捕获信号灯从终止的程序中并显示信息消息。
现在,您也可以在 SIGINT 上获取消息,前提是您给解释 shell 足够的时间来检查(更准确地说 - 因为我认为 shell 不会离开僵尸进程在这种情况下——报告状态) 其子进程。一种方法是使用wait
内置函数主动等待所有或指定进程更改状态。炸毁退出处理程序(例如,使用另一个sleep
)也可能是一种选择,但请注意,这实际上是解释器终止和检查其子级之间的竞争条件(因此阻塞wait
是执行此操作的安全方法)。