Чи є спосіб перенаправити вихід у файл без буферизації на unix / linux?


49

У мене тривалий пакетний процес, який видає деяку налагодження та обробляє інформацію для stdout. Якщо я просто запускаю з терміналу, я можу відслідковувати "де він є", але тоді даних стає занадто багато і прокручується з екрана.

Якщо я перенаправляю на вихід у файл '> out.txt', я отримую весь результат у підсумку, але він буферизований, тому я більше не бачу, що він робить зараз.

Чи є спосіб перенаправити вихід, але змусити його не буфер писати?


1
Чи можете ви, будь ласка, подивитись на мою (та @cnst) "дискусію" нижче, я здогадуюсь, єдине, що ви хочете, - це побачити вихід одночасно з тим, як записати його у файл. Якщо ви знайшли рішення, повідомте про це;)!
Бендж

2
більш актуальне питання unix.stackexchange.com/questions/25372
Тревор Бойд Сміт

Відповіді:


52

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

Це буфери stdoutдо рядка:

stdbuf -oL command > output

Це stdoutвзагалі вимикає буферизацію:

stdbuf -o0 command > output

aaarghhh ... У мого Ubuntu є лише 7,4 coreutils ... :(
Кальмарій

@Calmarius: компіляція coreutils має бути досить простою. Просто візьміть нову версію з ftp.gnu.org/gnu/coreutils і дайте їй піти. Це стандартний ./configure && makeтариф. Вам навіть не доведеться встановлювати його згодом, ви можете просто використати stdbufдвійкове вимкнено src/.
Едуардо Іванець

подвійний арг. мені це потрібно на старому дистрибуторі centos AND OSX, а також на Ubuntu.
edk750

більш обґрунтована відповідь unix.stackexchange.com/a/25378/5510
Тревор Бойд Сміт

Чи є спосіб примусити буфери труби / 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

-1 тому що: а) на відміну від прийнятої відповіді, це не працює, якщо ви хочете запустити команду у фоновому режимі (команда негайно припиняється, не закінчуючи, batch_processякщо ви додасте &до команди вище, принаймні, у моєму вікні Linux), що здається як надзвичайно поширений випадок використання, і б) тут немає пояснень, як працює ця заклинання.
Марк Амері

8

У Ubuntu unbufferпрограмний expect-devпакет (з пакету) зробив для мене трюк. Просто запустіть:

unbuffer your_command

і він не буферизує його.


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команду; якщо ваша система має її, вона бере аргумент імені файлу, весь текст, скинутий на stdout, копіюється у файл. Це дуже корисно, коли програма налаштування вимагає взаємодії.


Я знаю трюк 'script -a out.txt'. Мені було цікаво, чи є інший спосіб зробити процес написання не буферним.
Джеймс Дін

3

Особисто я віддаю перевагу конвеєрному виводу команди, яку я хочу вивчити tee.

scriptзаписує занадто багато інформації, включаючи терміни натискання клавіш, і багато символів, що не друкуються. Те, що teeекономить, для мене набагато читає людське.


Я також додав би "| менше" до командного рядка.
HUB

4
Я майже впевнений, що на teeце впливає і буферизація. Я часто все ще отримую часткові рядки, які відображаються трійником при розбитті виводу з findкоманд.
Магеллан

2

Перенаправляйте вихід у файл та виконайте tail -fкоманду командою.

Редагувати

Якщо це все ще страждає від буферизації, використовуйте функцію syslog (яка, як правило, небуферована). Якщо пакетний процес працює як скрипт оболонки, для цього можна використовувати команду реєстратора. Якщо пакетне завдання працює мовою скриптів, у будь-якому випадку має бути об'єкт реєстрації.


3
Це я зараз роблю, але процес буферизує запис у файл, і саме цього я хочу уникати.
Джеймс Дін

Дивіться мою редакцію для оновленої пропозиції.
wolfgangsz

1
Це не працює з очевидних причин. Хто, до біса, дає This answer is usefulвідповіді, які не працюють і не можуть працювати?
cnst

1

Ви можете використовувати teeкоманду, просто магію!

someCommand | tee logFile.logбуде як відображення в консолі і запис в лог - файл.


Не працює. teeне зупинить жодного буферизації.
cnst

1
@cnst Ефективно, teeне уникне деяких буферизацій, а лише дозволить вам ознайомитись з результатами. Це те, чого хотів @JamesDean (як я зрозумів його питання), але я думаю, що буферизація тут насправді не є проблемою. Якщо у вас є більше деталей, повідомте мене.
Бендж

Він хотів бачити вихід, і він не отримує жодного результату (нерозбірним способом), і все ж ви пропонуєте використовувати teeдля кращого перегляду результату, який не отримує?
cnst

1
Як я червоний @JamesDean питання: "Я перенаправляю на вихід у файл"> out.txt "" означає для мене відсутність консольного виходу, зачекайте, поки процес завершиться, поки весь вихід буде переспрямований. Під час використання >ви нічого не бачите на консолі. Я думаю, що @JamesDean використовує слово "буферизація", щоб описати це. Я опублікую коментар до його питання, щоб сказати більше про те, що він хоче.
Бендж
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.