Как команда внутри конвейера может прервать конвейер?

Запустите скрипт напрямую, используя shebang(#!/usr/bin/phpв первой строке, и пометьте скрипт как исполняемый ). ps axпокажет имя скрипта в выводе, например. /usr/bin/php /path/to/your/script.

В качестве альтернативы вы можете сохранить PID в другом файле из вызывающего скрипта. Чтобы проверить, запущен ли ваш скрипт, проверьте, существует ли процесс с этим PID (. Возможно, вам также следует проверить соответствие cmdlineили exec, поскольку PID используются повторно ).

Как поясняется в ответе @B Layer , ни один из этих двух вариантов не является надежным на 100%.

1
09.12.2019, 04:43
1 ответ

@mosvy очень помог ответ был в основном правильным, но есть проблема, заключающаяся в том, что b()всегда прерывает конвейер независимо от того, встречает ли sed /die/q"die ":

Входной поток содержит «матрицу»

$ b(){ sed /die/q && kill "$BASHPID"; }; printf '%s\n' pass die oops | b | cat; echo "${PIPESTATUS[@]}"
pass
die
0 143 0

Входной поток не содержит штампа

$ b(){ sed /die/q && kill "$BASHPID"; }; printf '%s\n' pass oops | b | cat; echo "${PIPESTATUS[@]}"
pass
oops
0 143 0

В версии @mosvy b()всегда прерывает конвейер, потому что sed /die/qвозвращает код выхода 0 (успех ), если встречает "die" или достигает конца входного потока поэтому b()всегда вызывает kill "$BASHPID".

В следующей версии я исправил ответ @mosvy так, что b()прерывает конвейер только когда он встречает "die" во входном потоке:

Входной поток содержит "die"

b() {
  sed '/die/{q 2}' || kill "$BASHPID"
}

# Send "die" to b.
printf '%s\n' pass die oops | b | cat

echo "${PIPESTATUS[@]}"

Выход:

pass
die
0 2 0

Входной поток не содержит штампа

b() {
  sed '/die/{q 2}' || kill "$BASHPID"
}

# Do not send "die" to b.
printf '%s\n' pass oops | b | cat

echo "${PIPESTATUS[@]}"

Выход:

pass
oops
0 0 0

Обратите внимание, что в этой версии b(), если sedвстречает "die", он вызывает команду q 2, которая приводит к немедленному завершению sedс кодом выхода 2 (ошибка ), а затем ||для вызова kill "$BASHPID", который завершает процесс b()в конвейере и прерывает конвейер. (Обратите внимание, что для этой версии требуется GNU sed, который расширяет команду q, чтобы он принимал код выхода.)

Как упоминает @mosvy, вместо совершения "ритуального самоубийства",b()может просто exitиз процесса:

b() {
  sed '/die/{q 2}' || exit 3
}

# Send "die" to b.
printf '%s\n' pass die oops | b | cat

echo "${PIPESTATUS[@]}"

Выход:

pass
die
0 3 0
1
27.01.2020, 23:55

Теги

Похожие вопросы