Сломал трубку, когда была прочитана первая строка - PullRequest
0 голосов
/ 02 сентября 2018

проблема

Необходимо остановить предыдущие команды в трубе, когда получена первая строка. То есть Команды остановки, когда fifo был закрыт для ввода.
Я считаю, что есть некоторые покупатели ..

История

Необходимо отправить запрос и получить ответ на / с простого TCP-сервера.

echo $REQUEST | nc localhost 3333  -q3

Это работает нормально, но всегда завершается через 3 секунды; без -q3 никогда не получит ответ.
И я нашел хорошее решение, как закрыть трубу с помощью awk:

echo $REQUEST | nc localhost 3333  -q3 | awk '{print;exit}'

Он работает очень хорошо в FISH, но все еще блокируется на 3 секунды в BASH и SH Я тестировал fish, sh и bash на Ubuntu 16 и MacOS X

Песочница

Например

sh -c  'echo line1; sleep 3; echo NEVER;'  | awk '{print;exit}'

Я ожидаю немедленного выхода, но он спит.

Другой способ остановить конвейер - это grep '' -m1, и он хорошо работает в FISH как awk, а не в BASH и SH.

Обход

mkfifo tempfi
( echo asdf; sleep 9; echo xxa; ) > tempfi &
awk '{print;exit}' <tempfi 
kill $!

выглядит некрасиво

1 Ответ

0 голосов
/ 02 сентября 2018

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

Вы можете не беспокоиться об этом с помощью замены процесса:

read -r line < <(echo asdf; sleep 9; echo xxa)
printf '%s\n' "$line"

... не ждет, пока субоболочка, запущенная echo asdf; sleep 9; echo xxa, завершится, прежде чем перейти от read к printf.

...