
В скрипте оболочки я хочу записать данные в stdin внешнего процесса X, используя именованный канал, и отправить stdout/stderr из другого именованного канала на текущий терминал.
Внешний процесс X получает stdin через PIPEIN и отправляет свой stdout/stderr в PIPEOUT.
tail -f $(tail -F PIPEOUT) & # (1) this is completely wrong, need help here
for i; do
echo "${i}" > PIPEIN # send stdin to X
done
echo "[stdin end]" > PIPEIN # signal that we are done writing (there might be a better way lol)
Итак, в приведенном выше скрипте мы уже запустили процесс X, он работает уже некоторое время. Но теперь, когда мы запускаем приведенный выше скрипт, мы хотим отправить X некоторый stdin и хотим прочитать stdout из процесса X, используя PIPEOUT.
То, что я пытаюсь сделать выше, — это настроить чтение из PIPEOUT перед отправкой stdin в X, чтобы убедиться, что я захватываю весь stdout/stderr X. Проблема в том, что я не знаю, как запустить какой-нибудь фоновый процесс (tail или cat для чтения из PIPEOUT) и отправить этот stdio в текущий терминал.
Кто-нибудь знает, о чем я говорю. Если я не ошибаюсь, мне просто нужно исправить строку с меткой (1) и как-то настроить чтение в фоновом режиме, которое может читать из PIPEOUT и как-то отправлять это stdio в текущий терминал/tty.
решение1
Я не совсем понимаю, что вы имели в виду tail -f $(tail -F PIPEOUT) &
. Это tail -f
файл, которыйявляется результатом tail -F
, который обычно никогда не завершается. Я предполагаю, что вы хотите вывести все, что проходит через трубу, сколько бы времени это ни заняло.
Проблема с just tail -f
в том, что он должен найти конец файла, прежде чем что-либо вывести, чего для pipe никогда не происходит. Вы можетевместо этого укажите tail
явную начальную точку-n +x
, выбрав строку, с которой нужно начать (с самого начала, индексация 1). tail -n 1 -f foo
отобразит все, что можно получить из foo
.
tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
for i in a b c d ; do
echo $i > PIPEIN
done
echo "[stdin end]" > PIPEIN
Однако обратите внимание, что это echo > foo
закроет foo после записи строки — команда на другом конце должна быть счастлива иметь дело с этим. Если этот пример искусственный и реальный ввод поступает откуда-то еще, вы можете проигнорировать это.
Обратите внимание также, чтопроцесс tail
никогда не прекратится— он продолжает ожидать, что что-то еще может пройти через канал. Вам придется убить его явно самостоятельно, возможно, с помощью управления заданиями вашей оболочки. Если в выводе есть некоторая закономерность, которая укажет на то, что это было сделано, вы можете обнаружитьretail
("хвост с регулярными выражениями")полезно — retail -n +1 -f -u REGEX PIPEOUT
завершится при REGEX
появлении совпадения строк. (В качестве отказа от ответственности: я написал retail
несколько лет назад именно для этой цели)
решение2
Если открыть PIPEIN для записи только один раз, программа завершится — даже если будет задержка в 2 секунды:
mkfifo PIPEIN PIPEOUT
tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
(
for i in a b c d ; do
echo $i
done
sleep 2
echo "[stdin end]"
) > PIPEIN
Если открыть fifo несколько раз, то читатель fifo может посчитать его закрытым, и, таким образом, писатель будет зависать до тех пор, пока не появится другой читатель, который начнет читать из fifo.
Поэтому спасение — открывать PIPEIN только один раз. В противном случае вы можете увидеть, что программа зависает.