直接进入:
while true; do
#--- MENU LOGIC HERE, stick response in $MENUEXIT
#----Deal with responses here
if [ $S1 == $MENUEXIT ];
then
tail -f /path-to-file
else
sleep 2
fi
done
我已尝试使其尽可能简单,如果您需要更多信息,请告诉我。
基本上,我将菜单置于循环中,因此,如果用户输入不正确或命令完成,则意味着重新显示菜单。
一切都运行正常,直到我添加了 tail 命令。
如果我从菜单中选择 tail 选项,tail 命令就会正常启动 - 但是,如果我点击Ctrl+ C,我希望 tail 终止并且菜单显示出来,但它却同时终止 tail和剧本。
我尝试了各种各样的方法,比如继续/陷阱等等,但是,我遇到了障碍,需要一些帮助吗?
答案1
当你发送如下信号时SIGINT
( CtrlC) 或SIGSTOP
( CtrlZ)从终端,信号被发送到前台进程组。也就是说,由前台作业(您的脚本)及其在前台的任何子进程(命令tail
)组成的组。这会导致所有这些进程退出(或通过处理信号来执行它们所做的任何操作)。您可以通过使用以下命令发送信号来测试差异kill
:
在一个终端中,执行此脚本(我test
在以下命令中调用它):
#! /bin/bash
while true
do
if [[ $1 = a ]]
then
yes
else
echo no
sleep 2
fi
done
在另一个文件中执行以下命令:
pstree -ps $(pgrep -f test)
pkill -f test
pstree -ps $(pgrep -f yes)
命令的输出将会像这样:
init(1)───lightdm(1032)───lightdm(1154)───init(1173)───x-terminal-emul(17009)───bash(24262)───test.sh(24996)───yes(24997)
# No output for pkill
init(1)───lightdm(1032)───lightdm(1154)───init(1173)───yes(24997)
(实际数字和程序可能会有所不同,但第一个 init 总是会有进程 1。)
如您所见,该yes
命令没有被杀死,而是被附加到,init
因为它的父级被杀死了。它仍然y
在第一个终端上愉快地打印 s。因此使用 杀死它pkill -f yes
。现在重复实验,但有一处变化。而不是pkill -f test
,而是:
kill -INT -25165
# Use the pid of test.sh given in parentheses in the output of pstree
# instead of 25165
注意前面的-
。在 Linux 中,对于该kill
命令,-25165
是进程组,其领导者具有 pid 25165
。因此,此命令相当于从终端发送中断。
当然,具体行为取决于 TTY、登录 shell 等的配置。这是我的理解。进一步阅读:
我建议:
- 发送
tail
到后台 - 捕获信号
- 终止后台进程。
- 移除陷阱
一个例子:
#! /bin/bash
kill_jobs ()
{
kill %1
}
while true
do
if [[ $1 = "a" ]]
then
trap kill_jobs INT
tail -f /var/log/syslog &
wait %%
shift #You don't need to shift, I just didn't want loop tail on this example
trap - INT
else
echo some output
sleep 2
fi
done
通过使用不同的函数进行捕获,并分别执行自己的清理工作,它可以变得非常强大。