Bash: Как заставить подпроцессы сценария завершаться, когда сценарий завершается? - PullRequest
11 голосов
/ 19 октября 2011

Вопрос относится к сценарию, например:

Сценарий

#!/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 процессы.

Ответы [ 2 ]

16 голосов
/ 19 октября 2011

Напишите ловушку для Ctrl+c и в ловушке убейте все подпроцессы. Поместите это перед вашей wait командой.

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

trap handle_sigint SIGINT
0 голосов
/ 07 февраля 2014

Простая альтернатива - использование трубы cat. У меня сработало следующее:

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

Если я нажму Ctrl-C до того, как последний номер будет напечатан на стандартный вывод. Это также работает, если генерирующая текст команда требует много времени, например «find /», то есть не только соединение с stdout через cat, но и дочерний процесс.

Для больших сценариев, в которых широко используются подпроцессы, самый простой способ убедиться в том, что поведение Ctrl-C с отступом заключает весь сценарий в подоболочку, например,

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

Я не уверен, однако, имеет ли это тот же эффект, что и ответ Эндрю (т.е. я не уверен, какой сигнал посылается подпроцессам). Также я проверил это только с cygwin, а не с родной оболочкой Linux.

...