Ответ 1
Вы можете обнаружить, что unbuffer
script, который поставляется с expect
, может помочь.
У меня есть script как:
#!/bin/bash
exec /usr/bin/some_binary > /tmp/my.log 2>&1
Проблема в том, что some_binary
отправляет все свои записи в stdout, а буферизация делает это так, что я вижу только вывод в кусках нескольких строк. Это раздражает, когда что-то застревает, и мне нужно посмотреть, что говорит последняя строка.
Есть ли способ сделать stdout небуферированным до того, как я сделаю exec, который повлияет на some_binary, чтобы он имел более полезный журнал?
(Оболочка script устанавливает только несколько переменных среды перед exec, поэтому решение в perl или python также будет возможно.)
Вы можете обнаружить, что unbuffer
script, который поставляется с expect
, может помочь.
GNU coreutils-8.5 также имеет команду stdbuf
для изменения буферизации потока ввода-вывода.
http://www.pixelbeat.org/programming/stdio_buffering/
Итак, в примере вашего примера просто вызовите:
exec stdbuf -oL /usr/bin/some_binary > /tmp/my.log 2>&1
Это позволит отображать текст сразу по очереди (как только строка будет завершена символом конца строки "\n"
в C). Если вам действительно нужен немедленный вывод, вместо этого используйте -o0
.
Этот способ может быть более желательным, если вы не хотите вводить зависимость expect
с помощью команды unbuffer
. С другой стороны, путь unbuffer
необходим, если вам нужно обмануть some_binary
, считая, что он сталкивается с реальным стандартным выходом tty.
Некоторые программы командной строки имеют возможность изменять поведение буферизации потока stdout. Так что путь, если доступен источник C...
# two command options ...
man file | less -p '--no-buffer'
man grep | less -p '--line-buffered'
# ... and their respective source code
# from: http://www.opensource.apple.com/source/file/file-6.2.1/file/src/file.c
if(nobuffer)
(void) fflush(stdout);
# from: http://www.opensource.apple.com/source/grep/grep-28/grep/src/grep.c
if (line_buffered)
fflush (stdout);
В качестве альтернативы использованию wait unbuffer script или изменения исходного кода программы вы также можете попытаться использовать script (1), чтобы избежать икоты stdout, вызванных трубой:
Смотрите: Обманите приложение, думая, что его stdin является интерактивным, а не протоколом
# Linux
script -c "[executable string]" /dev/null
# FreeBSD, Mac OS X
script -q /dev/null "[executable string]"
GNU Coreutils-8 включает в себя программу под названием stdbuf, которая по сути делает трюк LD_PRELOAD. Он работает на Linux и, как сообщается, работает над системами BSD.
Я просмотрел интернеты для ответа, и ни одна из них не работала для uniq
, которая слишком упряма для буфера всего, кроме stdbuf
:
{piped_command_here} | stdbuf -oL uniq | {more_piped_command_here}
Переменная среды может установить режим ввода-вывода терминала в небуферизованный.
export NSUnbufferedIO = YES
Это установит терминал небуферизованным для команд вывода C и Ojective-C.