linux - 使用 eval 的脚本启动的子进程不会在 ctrl+c 上中断

标签 linux bash macos

我知道之前有人在 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/

相关文章:

linux - 在 C 中将调用从 spawn 转换为 fork-exec

linux - 如何查看 root 的 bash_history?

linux - Bash脚本按编号归档文件

macos - 如何从命令行打开和关闭 os x 中的 Web 代理

c - 使用可加载内核模块的系统调用拦截中的参数似乎已损坏

linux - 如何在 linux shell 中进行求和

linux - 在 linux 中找到已删除用户的主目录

linux - 在一系列编号的文件中找到第一个丢失的文件

java - 从可用的不同版本中选择 Mac 中更新的 Java SDK

css - 有什么方法可以阻止 Apple OS 在表单字段、滚动条等上的原生样式吗?