Как сделать вывод любой команды оболочки небуферизованной?

Есть ли способ запускать команды оболочки без буферизации вывода?

Например, hexdump file | ./my_script будет передавать входные данные из hexdump в my_script только буферизованными фрагментами, а не построчно.

На самом деле я хочу знать общее решение, как сделать любую команду небуферизованной?


person bodacydo    schedule 12.08.2010    source источник
comment
больше вопросов, за которые проголосовали unix.stackexchange.com/questions/25372   -  person Trevor Boyd Smith    schedule 10.06.2016
comment
Возможно, см. Также stackoverflow.com/questions/7161821 /   -  person tripleee    schedule 08.02.2021


Ответы (5)


AFAIK, вы не можете сделать это без уродливых хаков. Запись в канал (или чтение из него) автоматически включает полную буферизацию, и вы ничего не можете с этим поделать :-(. «Буферизация строки» (что вам и нужно) используется только при чтении / записи терминала. Уродливые хаки делают именно это: они подключают программу к псевдотерминалу, так что другие инструменты в конвейере читают / записывают с этого терминала в режиме строчной буферизации. Вся проблема описана здесь:

На странице также есть несколько предложений (вышеупомянутые «уродливые уловки»), что делать, то есть использовать unbuffer или проделывать какие-то трюки с LD_PRELOAD.

person Nordic Mainframe    schedule 12.08.2010
comment
Спасибо. Я никогда раньше не слышал о псевдотерминалах. - person bodacydo; 12.08.2010

Попробуйте stdbuf, включенный в GNU coreutils и, следовательно, практически в любой дистрибутив Linux. Это устанавливает длину буфера для ввода, вывода и ошибки равной нулю:

stdbuf -i0 -o0 -e0 command
person lambshaanxy    schedule 28.08.2014
comment
Для меня это сработало лучше, чем unbuffer. stdbuf передавал какие-либо сигналы (SIGUSR2 в моем случае) я отправлял ему command (это то, что я хотел), а unbuffer, похоже, не хотел. - person ElDog; 11.04.2015
comment
stdbuf использует для этого один из вышеупомянутых уловок LD_PRELOAD и, следовательно, не работает со статически связанными исполняемыми файлами или исполняемыми файлами setuid. См. Этот вопрос для обсуждения: stackoverflow.com/questions / 13644024 / - person Nordic Mainframe; 04.07.2016
comment
Я нашел это очень полезным, но ограниченным, поскольку он не запускает скрипты неявно. Однако stdbuf -o0 bash запускает полный сеанс со всеми моими доступными сценариями и псевдонимами и без буферизации вывода ни для одной из команд, а это именно то, что я хотел. Конечно, при выходе из этого bash экземпляра буферизация была восстановлена. Я использую Ubuntu 16.04. - person AFH; 20.06.2017
comment
Мне это так понравилось, я поместил это первым в свой .bash_profile. if [[ "$0" == "-bash" ]]; then exec /usr/bin/stdbuf -i0 -oL -eL /bin/bash -l; fi - person IcarusNM; 24.08.2019
comment
Работал для меня в шаблоне exec для отправки вывода в файл журнала, со всей буферизацией строки вывода, а не с полностью отключенной буферизацией: exec > >(stdbuf -i0 -oL -eL awk '{print strftime("%Y-%m-%d %H:%M:%S"), $0 }' | stdbuf -i0 -oL -eL tee "$LOGFILE") 2>&1 - person JinnKo; 06.09.2019

Команда unbuffer из пакета expect отключает буферизацию вывода:
Ubuntu Справочная страница: unbuffer - unbuffer output

Пример использования:

unbuffer hexdump file | ./my_script
person Siu Ching Pong -Asuka Kenji-    schedule 12.08.2010
comment
unbuffer, похоже, объединяет stdout и stderr команды, хотя ... (!) - person olejorgenb; 10.05.2016
comment
@olejorgenb да, он объединяет stdout и stderr, это задумано: unbuffer использует expect и expect, чтобы имитировать взаимодействие человека с программой, и люди не видят, является ли вывод stdout или stderr. - person toolforger; 31.03.2019

Вы также можете использовать команду script для вывода hexdump строчной буферизации (hexdump будет запускаться в псевдотерминале, который заставляет hexdump думать, что он пишет свой стандартный вывод на терминал, а не на канал).

# cf. http://unix.stackexchange.com/questions/25372/turn-off-buffering-in-pipe/
stty -echo -onlcr
script -q /dev/null hexdump file | ./my_script         # FreeBSD, Mac OS X
script -q -c "hexdump file" /dev/null | ./my_script    # Linux
stty echo onlcr
person vroc    schedule 07.05.2013
comment
Я использовал параметр -f для очистки, не уверен, что это необходимо, но это сработало. - person Gringo Suave; 24.10.2013
comment
В моем случае stdbuf не удалось, но сценарий работает как шарм. Программа буферизует вывод, когда он передается в tee, но не при запуске в терминале. Итак, скрипт работает! Спасибо! - person TerrenceSun; 18.05.2016
comment
Очень умное решение, и оно работает !! Спасибо. :улыбка: - person xmnboy; 01.03.2017
comment
Только одна проблема: на странице script man, на которую ссылается this, некоторые интерактивные команды, такие как vi(1), создают мусор в машинописном файле. Сценарий лучше всего работает с командами, которые не управляют экраном, результаты предназначены для имитации печатного терминала. - person RandomDSdevel; 02.11.2017

Для решения этой проблемы следует использовать параметры grep или egrep --line-buffered. никаких других инструментов не требуется.

person Binghoo Dang    schedule 17.05.2021