本文介绍了由脚本使用eval启动的子流程在ctrl + c上不会中断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道之前曾在SO上问过类似的问题(例如),但我无法使其适用于我的情况.

I'm aware that similar questions have been asked before on SO (for example here) but I can't get it to work for my case.

我有一个名为 kubetail 的bash脚本,它可以评估一组背景命令从脚本开始,如下所示:

I have a bash script called kubetail which evaluates a set of background commands started from the script like this:

CMD="cat <( eval "${command_to_tail}" )"
eval "$CMD"

其中command_to_tail调用多个子过程( kubectl )并进行汇总将它们的输出合并为一个流.问题在于,在eval期间按下ctrl+c时,它不会在主脚本停止时中断子进程.例如,当我中断脚本后运行ps -Af | grep kubectl (kubectl由我的脚本生成)时,显示以下内容:

where command_to_tail calls several subprocesses (kubectl) and aggregates their output into one stream. The problem is that when ctrl+c is pressed during eval it won't interrupt the subprocesses when the main script stops. For example this is shown when I run ps -Af | grep kubectl after I've interrupted the script (the kubectl is spawned by my script):

$ 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上所有子进程的解决方案.有什么建议吗?

I've tried various forms of trap - INT but I fail to find a solution that kills all subprocesses on ctrl+c. Any suggestions?

推荐答案

您遇到的问题是由于所有子进程都在各自的进程ID下独立运行.发出ctrl + c时,您试图取消以原始PID运行的原始脚本.子流程不受影响.一个简单的类似示例是:

The problem you are having is due to all of the subprocesses running independently under there own process ID. When you issue ctrl + c you are attempting to cancel your original script running under its original PID. The subprocesses are unaffected. A simple analogous example is:

#!/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进程(每次迭代都会更改).

When you run the script and then try and cancel the script, control is very likely within the sleep PID and ctrl + c has no effect. If you want control over canceling the script at any point, then you will need to have each subprocess identify that a SIGINT was received by the parent to know an interrupt occurred. In some cases (as with sleep above), that is not directly possible when called from within the script as pressing ctrl + c will not affect the sleep process (which will change on each iteration).

在所有情况下都没有解决问题的灵丹妙药,因为所需的条件在很大程度上取决于您对子流程中可以执行的操作具有哪种控制方式,以及您的父脚本是否会完全迭代,这会导致每次迭代检查(例如临时文件的存在)是可行的解决方案.

There is no magic-bullet for solving this problem in all cases because what is required will largely depend on what type of control you have over what can be done in the subprocesses and whether your parent script iterates at all that would make a per-iteration check (like for the existence of a temp file) a workable solution.

这篇关于由脚本使用eval启动的子流程在ctrl + c上不会中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 14:36