У меня есть сценарий, который называет две команды:
long_running_command | print_progress
long_running_command
печать прогрессирует, но я недоволен им. Я использую print_progress
сделать это более хорошим (а именно, я печатаю прогресс одной строки).
Проблема: Соединение канал к stdout также активирует буфер 4K, таким образом, хорошая программа печати ничего не получает... ничто... ничто... много... :)
Как я могу отключить 4K
буфер для long_running_command
(не, у меня нет источника)?
Можно использовать unbuffer
команда (который стал частью expect
пакет), например.
unbuffer long_running_command | print_progress
unbuffer
подключения к long_running_command
через псевдотерминал (имущество), которое заставляет систему рассматривать его как интерактивный процесс, поэтому не используя буферизацию 4 кибибитов в конвейере, который является вероятной причиной задержки.
Для более длинных конвейеров Вам, вероятно, придется освободить буфер каждая команда (кроме заключительной), например.
unbuffer x | unbuffer -p y | z
Другой способ освежевать эту кошку состоит в том, чтобы использовать stdbuf
программа, которая является частью Coreutils GNU (FreeBSD также имеет свой собственный).
stdbuf -i0 -o0 -e0 command
Это выключает буферизацию полностью для входа, вывода и ошибки. Для некоторых приложений буферизация строки может более подойти по причинам производительности:
stdbuf -oL -eL command
Обратите внимание, что это только работает на stdio
буферизация (printf()
, fputs()
...) для динамично связанных приложений, и только если то приложение иначе не корректирует буферизацию своих стандартных потоков отдельно, хотя это должно покрыть большинство приложений.
sudo stdbuff … command
работы, хотя stdbuff … sudo command
не сделал. спасибо
– natevw
10.07.2013, 09:05
stdbuf
не работает с tee
, потому что tee
перезаписывает значения по умолчанию, установленные stdbuf
. См. страницу руководства stdbuf
.
– ceving
30.06.2014, 14:51
stdbuf
использование LD_PRELOAD
механизм для вставки его собственной динамично загруженной библиотеки libstdbuf.so
. Это означает, что не будет работать с этими исполняемыми файлами видов: с setuid или набором возможностей файла, статически связанным, не использующий стандарт libc. В этих случаях лучше использовать решения с unbuffer
/ script
/ socat
. См. также stdbuf с setuid/capabilities.
– pabouk
12.10.2015, 12:20
Если это - проблема с libc изменение его буферизации / сбрасывание, когда произведенный не переходит к терминалу, необходимо попробовать socat. Можно создать двунаправленный поток почти между любым видом механизма ввода-вывода. Один из тех является разветвленной программой, говорящей с псевдо tty.
socat EXEC:long_running_command,pty,ctty STDIO
То, что это делает,
Если это дает Вам тот же вывод как long_running_command
, затем можно продолжить канал.
Редактирование: Ничего себе, не видел освобождать буфер ответ! Ну, socat является большим инструментом так или иначе, таким образом, я мог бы просто оставить этот ответ
socat -u exec:long_running_command,pty,end-close -
здесь
– Stéphane Chazelas
07.08.2015, 16:10
Это раньше имело место и вероятно все еще имеет место, что, когда стандартный вывод записан в терминал, это - строка, буферизованная по умолчанию - когда новая строка записана, строка записана в терминал. Когда стандартный вывод отправляется в канал, он полностью буферизуется - таким образом, данные только отправляются в следующий процесс в конвейере, когда стандартный буфер ввода-вывода заполнен.
Это - источник проблемы. Я не уверен, существует ли очень, можно сделать для фиксации его, не изменяя программу, пишущую в канал. Вы могли использовать setvbuf()
функция с _IOLBF
отметьте для безусловного помещения stdout
в строку буферизовал режим. Но я не вижу простой способ осуществить это на программе. Или программа может сделать fflush()
в соответствующих точках (после каждой строки вывода), но тот же комментарий применяется.
Я предполагаю, что при замене канала псевдотерминалом, затем стандартная библиотека I/O думала бы, что вывод был терминалом (потому что это - тип терминала), и выровнял бы буфер автоматически. Это - сложный способ иметь дело с вещами, все же.
Я не думаю, что проблема с каналом. Это кажется, что Ваш длительный процесс не сбрасывает свой собственный буфер достаточно часто. Изменение размера буфера канала было бы взломом для обхода его, но я не думаю его возможное, не восстанавливая ядро - что-то, что Вы не хотели бы делать как взлом, поскольку это, вероятно, неохотно влияет на большое количество других процессов.
Для grep
, sed
и awk
можно вынудить вывод быть буферизованной строкой. Можно использовать:
grep --line-buffered
Вывод силы, чтобы быть буферизованной строкой. По умолчанию вывод является строкой, буферизованной, когда стандартный вывод является терминалом и блоком, буферизованным иначе.
sed -u
Сделайте выходную строку буферизованной.
Посмотрите эту страницу для получения дополнительной информации: http://www.perkin.org.uk/posts/how-to-fix-stdio-buffering.html
Еще один способ включить буферизующий строку режим вывода для long_running_command
должен использовать script
управляйте что выполнения Ваш long_running_command
в псевдотерминале (имущество).
script -q /dev/null long_running_command | print_progress # FreeBSD, Mac OS X
script -c "long_running_command" /dev/null | print_progress # Linux
script
такая старая команда, это должно быть доступно на всех подобных Unix платформах.
– Aaron Digulla
20.01.2013, 15:01
-q
на Linux: script -q -c 'long_running_command' /dev/null | print_progress
– jfs
11.04.2013, 15:51
stdin
, который лишает возможности выполнять такой long_running_command
в фоновом режиме, по крайней мере, при запуске с интерактивного терминала. К обходному решению я смог перенаправить stdin от /dev/null
, начиная с моего long_running_command
не использует stdin
.
– haridsv
15.11.2013, 14:44
expect_unbuffer
и находится вexpect-dev
пакет, неexpect
пакет – bdonlan 24.01.2011, 13:14expect-dev
предоставляет обоимunbuffer
иexpect_unbuffer
(первый - символьная ссылка на последнего). Ссылки доступны с тех порexpect 5.44.1.14-1
(2009). – jfs 11.04.2013, 16:00unbuffer
в основномexpect
пакет на debian теперь (это - все еще символьная ссылка наexpect_unbuffer
, который является также в основномexpect
пакет) – cas 05.11.2015, 01:50