Тройник не получает всю продукцию из трубы

12

У меня есть скрипт, выполняющий команды, такие как:

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH;./some_app -i $INDEX | tee $LOG
echo "Number of errors: $(grep "ERROR" $LOG | wc -l)"

Проблема, вероятно, в трубе tee. Похоже, не получить весь вывод. Когда приложение завершает работу, последние несколько строк вывода (обычно те, которые содержат фатальную ошибку) отсутствуют. Когда я запускаю приложение без канала, teeя получаю их в выводе.

Как я могу заставить скрипт ждать, пока тройник завершит обработку всего вывода?

Ладислав Мрнка
источник
Работает ли он нормально, если вы используете файл, а не стандартный вывод?
Pilot6

Ответы:

23

Вероятно, фатальная ошибка возникает в STDERR (2), а не в STDOUT (1). Вы можете перенаправить STDERR в STDOUT с помощью, 2>&1а затем канал должен захватить его тоже.

./some_app -i $INDEX 2>&1 | tee $LOG

Если у вас есть проблемы с буферизацией, вы можете перевести ее в состояние без буферизации:

stdbuf -o0 ./some_app -i $INDEX 2>&1 | tee $LOG
Оли
источник
Хорошо, мы приближаемся. Теперь я вижу, что печатается фатальная ошибка, но опять же она не завершена. Строка с ошибкой просто заканчивается посередине, а вывод эха продолжается. Все еще есть проблема с очисткой буфера или просто ожиданием завершения этой части.
Ладислав Мрнка
Ред. По моему опыту, это довольно редкое явление, когда при выходе что-то полностью проскальзывает через буферы, но это того стоит.
Оли
1
Выполнено! Спасибо. Возможно, я задаю слишком много вопросов, но кто-нибудь понимает, почему мне нужно отключить буферизацию при передаче в другой процесс?
Ладислав Мрнка
@ Оли Очень хороший!
Pilot6
6

Поскольку сообщения об ошибках обычно отображаются в STDERR (дескриптор файла 2), вам необходимо перенаправить STDOUT и STDERR в tee:

./some_app -i "$INDEX" |& tee "$LOG"

Когда вы это делаете, ./some_app -i $INDEX | tee $LOGвы только перенаправляете STDOUT на tee.

|& приведет к перенаправлению как STDOUT, так и STDERR.

Если вы не можете перенаправить только STDOUT (как вы были):

./some_app -i "$INDEX" | tee "$LOG"

С другой стороны, если вы хотите перенаправить только STDERR:

./some_app -i "$INDEX" 2>&1 >/dev/null | tee "$LOG"
heemayl
источник