Сценарий Bash не выходит сразу же, когда вызывается " exit


У меня есть следующий сценарий bash:

tail -F -n0 /private/var/log/system.log | while read line 
do
    if [ ! `echo $line | grep -c 'launchd'` -eq 0 ]; then
        echo 'launchd message'
        exit 0
    fi
done

По какой-то причине он повторяется launchd message, ожидая целых 5 секунд, и затем выходит.

Почему это происходит и как я могу заставить его выйти сразу же после того, как он эхом отзывается launchd message?

3 6

3 ответа:

Поскольку вы используете трубу, цикл while выполняется в подрешетке. Вместо этого запустите его в главной оболочке.

#!/bin/bash

while ...
do
   ...
done < <(tail ...)

Как указывает Игнасио, ваш tail | while создает подрешетку. Задержка вызвана тем, что он ждет следующей строки, которая будет записана в файл журнала, прежде чем все закроется.

Вы можете добавить эту строку непосредственно перед командой exit, Если вы предпочитаете не использовать подстановку процесса:

kill -SIGPIPE $$
К сожалению, я не знаю никакого способа управления кодом выхода с помощью этого метода. Это будет 141, что равно 128 + 13 (сигнальное число SIGPIPE).

Если вы пытаетесь сделать запуск демона, зависящего от запуска другого демона, возможно, есть лучший способ сделать это.

Кстати, если вы действительно пишете сценарий Bash (который вы должны были бы использовать для подстановки процесса <()), Вы можете написать свой if следующим образом: if [[ $line == *launchd* ]].

Вы также можете выйти из подсети с контрольным кодом выхода, а затем проверить значение "$?"чтобы получить тот же эффект, который вы ищете:

tail -F -n0 /private/var/log/system.log | while read line 
do
    if [ ! `echo $line | grep -c 'launchd'` -eq 0 ]; then
        echo 'launchd message'
        exit 10
    fi
done
if [ $? -eq 10 ]; then exit 0; fi