оператор трубы между двумя блоками - PullRequest
1 голос
/ 12 января 2020

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

Как эти два блока работают вместе, и каково поведение трубы, которая разделяет их?

function isTomcatUp {

    # Use FIFO pipeline to check catalina.out for server startup notification rather than
    # ping with an HTTP request. This was recommended by ForgeRock (Zoltan).

    FIFO=/tmp/notifytomcatfifo
    mkfifo "${FIFO}" || exit 1
    {
        # run tail in the background so that the shell can
        # kill tail when notified that grep has exited
        tail -f $CATALINA_HOME/logs/catalina.out &
        # remember tail's PID
        TAILPID=$!
        # wait for notification that grep has exited
        read foo <${FIFO}
        # grep has exited, time to go
        kill "${TAILPID}"
    } | {
        grep -m 1 "INFO: Server startup"
        # notify the first pipeline stage that grep is done
        echo >${FIFO}
    }
    # clean up
    rm "${FIFO}"
}

Код Источник: https://www.manthanhd.com/2016/01/15/waiting-for-tomcat-to-start-up-in-a-script/

Ответы [ 2 ]

3 голосов
/ 12 января 2020

bash имеет целый набор составных команд, которые работают так же, как простые команды. Наиболее уместным здесь является то, что каждая составная команда имеет свой собственный стандартный ввод и стандартный вывод.

{ ... } - это одна из таких составных команд. Каждая команда внутри группы наследует свой стандартный ввод и вывод от группы, поэтому в результате стандартный вывод группы является объединением стандартного вывода ее дочерних элементов. Кроме того, каждая команда внутри по очереди читает со стандартного ввода группы. В вашем примере ничего интересного не происходит, потому что grep использует весь стандартный ввод, и никакая другая команда не пытается прочитать его. Но рассмотрим этот пример:

$ cat tmp.txt
foo
bar
$ { read a; read b; echo "$b then $a"; } < tmp.txt
bar then foo

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

$ read a < tmp.txt
$ read b < tmp.txt

, где a и b будут содержать foo, потому что каждая команда read открывает tmp.txt заново, и обе читают первую строку.

2 голосов
/ 12 января 2020

Операции { …; } группируют команды так, что перенаправления ввода / вывода применяются ко всем командам в нем. { должно быть отдельным, как если бы это было имя команды; } должен начинаться с точки с запятой или новой строки и быть также отдельным. Команды не выполняются в под-оболочке, в отличие от ( … ), который также имеет некоторые различия по синтаксису c.

В вашем сценарии у вас есть две такие группировки, соединенные каналом. Из-за конвейера каждая группа имеет значение в вложенной оболочке, но не находится в вложенной оболочке из-за фигурных скобок.

Первая группа запускает tail -f в файле в фоновом режиме, а затем ждет закрытия FIFO, чтобы он мог убить tail -f. Вторая часть ищет первое вхождение некоторой определенной c информации и, когда она находит ее, останавливает чтение и запись в FIFO, чтобы освободить все.

Как и в любом конвейере, состояние выхода - это состояние последней группы - которая, вероятно, будет 0, потому что echo успешно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...