【问题标题】:Bash: How do I make sub-processes of a script be terminated, when the script is terminated?Bash:当脚本终止时,如何终止脚本的子进程?
【发布时间】:2011-12-10 16:25:57
【问题描述】:

该问题适用于如下脚本:

脚本

#!/bin/sh

SRC="/tmp/my-server-logs"

echo "STARTING GREP JOBS..."
for f in `find ${SRC} -name '*log*2011*' | sort --reverse`
do
    (
        OUT=`nice grep -ci -E "${1}" "${f}"`
        if [ "${OUT}" != "0" ]
        then
            printf '%7s : %s\n' "${OUT}" "${f}"
        else
            printf '%7s   %s\n' "(none)" "${f}"
        fi
    ) &
done

echo "WAITING..."
wait

echo "FINISHED!"

当前行为

在控制台中按Ctrl+C 会终止脚本,但不会终止已经运行的grep 进程。

【问题讨论】:

    标签: linux bash subprocess termination


    【解决方案1】:

    为Ctrl+c 编写一个陷阱,并在该陷阱中杀死所有子进程。把它放在你的wait 命令之前。

    function handle_sigint()
    {
        for proc in `jobs -p`
        do
            kill $proc
        done
    }
    
    trap handle_sigint SIGINT
    

    【讨论】:

    • 谢谢!效果很好!除了我的 bash 在 handle_sigint 之前预期 function。
    • 我已将function 添加到脚本中。
    • 好吧,这里有一个问题:当脚本在 数百个 文件上运行时,并非所有 进程都会立即启动(这很好) .遗憾的是,这会导致Ctrl+C 上只有一小部分 进程终止。我想,在终止期间在陷阱循环内,其他人正在开始。建议? (在主循环之前移动陷阱及其功能没有帮助)
    • stackoverflow.com/questions/360201/… 看起来很有用。 trap "kill 0" SIGINT 在我的机器上工作。
    • 注意:脚本的第一行需要阅读#!/bin/bash,而不是#!/bin/sh,这样才能正常工作。
    【解决方案2】:

    一个简单的替代方法是使用cat 管道。以下对我有用:

    echo "-" > test.text; 
    for x in 1 2 3; do 
        ( sleep $x; echo $x | tee --append test.text; ) & 
    done | cat
    

    如果我在最后一个数字打印到标准输出之前按 Ctrl-C。如果生成文本的命令需要很长时间,例如“find /”,它也可以工作,即它不仅是通过 cat 与标准输出的连接被杀死,而且实际上是子进程。

    对于大量使用子进程的大型脚本,确保缩进 Ctrl-C 行为的最简单方法是将整个脚本包装到这样的子 shell 中,例如

    #!/usr/bin/bash
    (
        ...
    ) | cat
    

    我不确定这是否与 Andrew 的回答具有完全相同的效果(即我不确定将什么信号发送到子进程)。此外,我只使用 cygwin 测试了这个,而不是使用原生 Linux shell。

    【讨论】:

      猜你喜欢
      • 2012-10-24
      • 2010-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多