Скрипт Bash не завершается сразу после вызова `exit` - PullRequest
6 голосов
/ 29 октября 2010

У меня есть следующий скрипт 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 ]

9 голосов
/ 29 октября 2010

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

#!/bin/bash

while ...
do
   ...
done < <(tail ...)
3 голосов
/ 29 октября 2010

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

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

kill -SIGPIPE $$

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

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

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

2 голосов
/ 26 апреля 2013

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

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
...