bash: заставить процесс exec'd иметь стандартный буфер без буферизации - PullRequest
20 голосов
/ 26 июля 2010

У меня есть такой скрипт:

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

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

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

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

Ответы [ 6 ]

28 голосов
/ 30 июля 2010

GNU coreutils-8.5 также имеет команду stdbuf для изменения буферизации потока ввода-вывода:

http://www.pixelbeat.org/programming/stdio_buffering/

Итак, в вашем примере,просто вызовите:

stdbuf -oL /usr/bin/some_binary > /tmp/my.log 2>&1

Это позволит тексту отображаться сразу же построчно (после завершения строки символом конца строки "\n" в C).Если вы действительно хотите немедленный вывод, используйте вместо него -o0.

Этот способ может быть более желательным, если вы не хотите вводить зависимость для expect с помощью команды unbuffer.Способ unbuffer, с другой стороны, необходим, если вам нужно обмануть some_binary, думая, что он сталкивается с реальным стандартным выводом tty.

13 голосов
/ 26 июля 2010

Может оказаться, что скрипт unbuffer, поставляемый с expect, может помочь.

11 голосов
/ 26 июля 2010

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

В качестве альтернативы использованию сценария небуферизации ожидаемого или изменению исходного кода программы, вы также можете попробовать использовать сценарий (1), чтобы избежать сбоев stdout, вызванных каналом:

См .: Обманите приложение, думая, что его стандартный интерфейс интерактивный, а не труба

# Linux
script -c "[executable string]" /dev/null

# FreeBSD, Mac OS X
script -q /dev/null "[executable string]"
3 голосов
/ 10 февраля 2016

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

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

2 голосов
/ 20 июля 2016

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

export NSUnbufferedIO = YES

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

2 голосов
/ 23 декабря 2013

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

...