Чтение stdout / stderr из подоболочки в родительский

В сценарии оболочки я хочу писать в 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.

0
07.07.2017, 10:36
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 только один раз. В противном случае вы можете увидеть, что программа зависает.

0
28.01.2020, 02:33

Мне не совсем понятно, что вы хотели 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несколько лет назад именно для этой цели)

2
28.01.2020, 02:33

Теги

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