Есть ли способ перенаправить вывод в файл без буферизации в Unix / Linux?

49

У меня есть длительный пакетный процесс, который выводит некоторую информацию отладки и процесса на стандартный вывод. Если я просто запускаю из терминала, я могу отслеживать «где он находится», но тогда данные становятся слишком большими и прокручиваются за пределы экрана.

Если я перенаправляю на вывод в файл '> out.txt', я в конечном итоге получаю весь вывод, но он буферизуется, поэтому я больше не вижу, что он делает сейчас.

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

Джеймс Дин
источник
1
Не могли бы вы взглянуть на мои (и @cnst's) «дебаты» ниже, я предполагаю, что единственное, что вам нужно, - это увидеть результат одновременно с записью его в файл. Если вы нашли решение, сообщите нам об этом;)!
Бендж
2
больше поднятых вопросов unix.stackexchange.com/questions/25372
Тревор Бойд Смит

Ответы:

52

Вы можете явно установить параметры буферизации стандартных потоков, используя setvbufвызов в C (см. Эту ссылку ), но если вы пытаетесь изменить поведение существующей программы, попробуйте stdbuf( coreutilsочевидно, что это начинается с версии 7.5).

Это буферизует stdoutдо строки:

stdbuf -oL command > output

Это полностью отключает stdoutбуферизацию:

stdbuf -o0 command > output
Эдуардо Иванец
источник
аааааа ... В моей Ubuntu есть только 7.4 coreutils ... :(
Calmarius
@ Calmarius: компиляция coreutils должна быть довольно простой. Просто скачайте новую версию с ftp.gnu.org/gnu/coreutils и попробуйте . Это стандартная ./configure && makeплата за проезд. После этого вам даже не нужно устанавливать его, вы можете просто stdbufотключить бинарный файл src/.
Эдуардо Иванец
двойной арг. Мне нужно это на старом дистрибутиве Centos и OSX, а также на Ubuntu.
edk750
больше голосов с ответом unix.stackexchange.com/a/25378/5510
Тревор Бойд Смит
Есть ли способ принудительно использовать буферы pipe / printf для уже запущенного процесса с известным PID?
Мворисек
9

Вы можете получить буферизованный вывод в файл, используя scriptкоманду следующим образом:

stty -echo -onlcr   # avoid added \r in output
script -q /dev/null batch_process | tee output.log        # Mac OS X, FreeBSD
script -q -c "batch_process" /dev/null | tee output.log   # Linux
stty echo onlcr
Melder
источник
-1 потому что: a) в отличие от принятого ответа, это не сработает, если вы хотите выполнить команду в фоновом режиме (команда немедленно завершается без завершения, batch_processесли вы добавляете &команду выше, по крайней мере на моем компьютере с Linux), что кажется как чрезвычайно распространенный вариант использования, и б) здесь нет объяснения того, как работает это заклинание.
Марк Амери
8

В Ubuntu пакет с unbufferпрограммой (из expect-devпакета) помог мне. Просто беги:

unbuffer your_command

и это не буферизует это.

Calmarius
источник
6

Самое простое решение, которое я нашел (не нужно было устанавливать какие-либо сторонние пакеты), было упомянуто в аналогичной теме на сайте Unix & Linux : используйте scriptкоманду. Он старый и, вероятно, уже установлен.

$ script -q /dev/null long_running_command | print_progress       # FreeBSD, Mac OS X
$ script -q -c "long_running_command" /dev/null | print_progress  # Linux

Обратите внимание, что первым параметром имени файла для scriptкоманды является записываемый файл журнала . Если вы просто запустите script -q your_command, вы перезапишете команду с отступом для запуска с файлом журнала. Проверьте man script, чтобы быть в безопасности, прежде чем пытаться это.

Стив ХХХ
источник
4

попробуйте scriptкоманду; если ваша система имеет его, он принимает имя файла в качестве аргумента, весь текст, выгруженный на стандартный вывод, копируется в файл. Это очень полезно, когда программа установки требует взаимодействия.

Крис С
источник
Я знаю трюк «скрипт -a out.txt». Мне было интересно, есть ли другой способ сделать процесс записи не буферным.
Джеймс Дин
3

Лично я предпочитаю вывод команды, которую я хочу изучить tee.

scriptзаписывает слишком много информации, включая время нажатия клавиш, и много непечатаемых символов. То, что teeспасает, гораздо более читабельно для меня.

Павел Бродацкий
источник
Я бы также добавил «| меньше» в командную строку.
HUB
4
Я уверен, что teeэто также влияет на буферизацию. Я часто до сих пор получаю частичные строки, отображаемые при разбиении вывода findкоманд.
Магеллан
2

Перенаправьте вывод в файл и выполните файл с помощью tail -fкоманды.

редактировать

Если это все еще страдает от буферизации, тогда используйте средство системного журнала (которое обычно небуферизовано). Если пакетный процесс выполняется как сценарий оболочки, вы можете использовать команду logger для этого. Если пакетное задание выполняется на языке сценариев, в любом случае должна быть возможность ведения журнала.

wolfgangsz
источник
3
Это то, что я делаю сейчас, но процесс буферизует запись в файл, и это именно то, чего я хочу избежать.
Джеймс Дин
Смотрите мое изменение для обновленного предложения.
wolfgangsz
1
Это не работает по понятным причинам. Кто, черт возьми, выдает This answer is usefulза ответы, которые не работают и не могут работать?
2013 года
1

Вы можете использовать teeкоманду, просто волшебство!

someCommand | tee logFile.logоба отобразятся в консоли и запишутся в файл журнала.

Benj
источник
Не работает teeне остановит буферизацию.
2013 года
1
@cnst Эффективно, teeне избежит некоторой буферизации, но только позволит вам посмотреть, что выводится. Это то, что хотел @JamesDean (как я не понял его вопрос), но я думаю, что буферизация здесь не является проблемой. Если у вас есть более подробная информация, дайте мне знать.
Бендж
Он хотел видеть выходные данные, и он не получает никаких выходных данных (небуферизованным образом), и все же вы предлагаете использовать, teeчтобы получить лучшее представление о выходных данных, которые вы не получаете?
2013 г.
1
Как я отвечаю на вопрос @JamesDean: «Я перенаправляю на вывод в файл '> out.txt'», значит для меня нет вывода на консоль, дождитесь завершения процесса, пока весь вывод перенаправлен. Когда вы используете, >вы ничего не видите на консоли. Я думаю, @JamesDean использует слово «буферизация», чтобы описать это. Я отправлю комментарий на его вопрос, чтобы он сказал больше о том, чего он хочет.
Benj