Подтвердить что ты не робот

Bash: принудительно выполнить команду exec'd, чтобы иметь unbuffered stdout

У меня есть script как:

#!/bin/bash
exec /usr/bin/some_binary > /tmp/my.log 2>&1

Проблема в том, что some_binary отправляет все свои записи в stdout, а буферизация делает это так, что я вижу только вывод в кусках нескольких строк. Это раздражает, когда что-то застревает, и мне нужно посмотреть, что говорит последняя строка.

Есть ли способ сделать stdout небуферированным до того, как я сделаю exec, который повлияет на some_binary, чтобы он имел более полезный журнал?

(Оболочка script устанавливает только несколько переменных среды перед exec, поэтому решение в perl или python также будет возможно.)

4b9b3361

Ответ 1

Вы можете обнаружить, что unbuffer script, который поставляется с expect, может помочь.

Ответ 2

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.

Ответ 3

Некоторые программы командной строки имеют возможность изменять поведение буферизации потока 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]"

Ответ 4

GNU Coreutils-8 включает в себя программу под названием stdbuf, которая по сути делает трюк LD_PRELOAD. Он работает на Linux и, как сообщается, работает над системами BSD.

Ответ 5

Я просмотрел интернеты для ответа, и ни одна из них не работала для uniq, которая слишком упряма для буфера всего, кроме stdbuf:

{piped_command_here} | stdbuf -oL uniq | {more_piped_command_here}

Ответ 6

Переменная среды может установить режим ввода-вывода терминала в небуферизованный.

export NSUnbufferedIO = YES

Это установит терминал небуферизованным для команд вывода C и Ojective-C.