В сценарии оболочки я хочу писать в 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. Проблема в том, что я не знаю, как запустить какой-то фоновый процесс (хвост или кот для чтения из PIPEOUT) и отправить этот stdio на текущий терминал.
Кто-нибудь знает, о чем я говорю. Если я не ошибаюсь, мне просто нужно исправить строку с меткой (1) и каким-то образом настроить чтение в фоновом режиме, которое может читать из PIPEOUT и каким-то образом отправлять это stdio на текущий терминал / tty.
При открытии 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 только один раз. В противном случае вы можете увидеть, что программа зависает.
Мне не совсем понятно, что вы хотели tail -f $(tail -F PIPEOUT) &
сделать. Это tail -f
в файле, что является результатом tail -F
, который обычно никогда не завершается. Я предполагаю, что вы хотите вывести все, что проходит через канал, сколько бы времени это ни заняло.
Проблема только с tail -f
заключается в том, что он должен найти конец файла, прежде чем что-либо выводить, чего для конвейера никогда не происходит. Вместо этого вы можете указать 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
несколько лет назад именно для этой цели)