我知道之前有人在 SO 上提出过类似的问题(例如 here ),但我无法让它适用于我的案例。
我有一个名为 kubetail 的 bash 脚本它评估一组从脚本开始的后台命令,如下所示:
CMD="cat <( eval "${command_to_tail}" )"
eval "$CMD"
其中 command_to_tail
调用多个子进程 ( kubectl ) 并将它们的输出聚合到一个流中。问题在于,当在 eval
期间按下 ctrl+c
时,它不会在主脚本停止时中断子进程。例如,当我运行 ps -Af | 时显示。 grep kubectl
after 我中断了脚本(kubectl
由我的脚本生成):
$ ps -Af | grep kubectl
501 85748 85742 0 9:48AM ttys014 0:00.16 kubectl --context= logs pod-4074277481-3tlx6 core -f --since=10s --namespace=
501 85750 85742 0 9:48AM ttys014 0:00.17 kubectl --context= logs pod-4074277481-9r224 core -f --since=10s --namespace=
501 85752 85742 0 9:48AM ttys014 0:00.16 kubectl --context= logs pod-4074277481-hh9bz core -f --since=10s --namespace=
我已经尝试了各种形式的 trap - INT
但我没能找到一个解决方案来杀死 ctrl+c
上的所有子进程。有什么建议吗?
最佳答案
您遇到的问题是由于所有子进程都在自己的进程 ID 下独立运行。当您发出 ctrl + c
时,您正试图取消在其原始 PID 下运行的原始脚本。子进程不受影响。一个简单的类比例子是:
#!/bin/bash
declare -i cnt=1
while [ "$cnt" -lt 100 ]; do
printf "iteration: %2d\n" "$cnt"
sleep 5
((cnt++))
done
当您运行脚本然后尝试取消脚本时,控制很可能在 sleep
PID 内,而 ctrl + c
无效。如果你想控制在任何时候取消脚本,那么你需要让每个子进程识别父进程收到了 SIGINT
以知道中断发生了。在某些情况下(如上面的 sleep
),当从脚本中调用时这是不可能的,因为按 ctrl + c
不会影响 sleep
过程(每次迭代都会改变)。
在所有情况下都没有解决此问题的 Elixir ,因为所需的内容在很大程度上取决于您对子流程中可以完成的事情的控制类型以及您的父脚本是否完全迭代会产生每次迭代检查(例如是否存在临时文件)是一个可行的解决方案。
关于linux - 使用 eval 的脚本启动的子进程不会在 ctrl+c 上中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44734291/