Apakah ada cara untuk mengarahkan output ke file tanpa buffering di unix / linux?

49

Saya memiliki proses batch yang berjalan lama yang menampilkan beberapa debug dan memproses informasi ke stdout. Jika saya hanya menjalankan dari terminal saya dapat melacak 'di mana itu' tetapi kemudian data menjadi terlalu banyak dan muncul dari layar.

Jika saya mengarahkan kembali ke output ke file '> out.txt' Saya mendapatkan seluruh output pada akhirnya tetapi buffered sehingga saya tidak bisa lagi melihat apa yang dilakukannya sekarang.

Apakah ada cara untuk mengarahkan output tetapi membuatnya tidak buffer menulisnya?

James Dean
sumber
1
Bisakah Anda melihat "debat" saya (dan @cnst) di bawah ini, saya kira satu-satunya hal yang Anda inginkan adalah melihat output dalam waktu yang sama dengan masuk ke file. Jika Anda menemukan solusi, beri tahu kami;)!
Benj
2
lebih banyak pertanyaan terselubung unix.stackexchange.com/questions/25372
Trevor Boyd Smith

Jawaban:

52

Anda dapat secara eksplisit mengatur opsi buffering stream standar menggunakan setvbufpanggilan dalam C (lihat tautan ini ), tetapi jika Anda mencoba untuk memodifikasi perilaku program yang ada coba stdbuf(bagian dari coreutilsmulai dengan versi 7.5 tampaknya).

Ini buffer stdouthingga garis:

stdbuf -oL command > output

Ini menonaktifkan stdoutbuffering sama sekali:

stdbuf -o0 command > output
Eduardo Ivanec
sumber
aaarghhh ... Ubuntu saya hanya memiliki 7,4 coreutils ... :(
Calmarius
@Calmarius: mengkompilasi coreutils seharusnya cukup mudah. Hanya ambil versi baru dari ftp.gnu.org/gnu/coreutils dan cobalah. Ini ./configure && maketarif standar . Anda bahkan tidak perlu menginstalnya setelah itu, Anda hanya dapat menggunakan stdbufbiner off src/.
Eduardo Ivanec
argh ganda. Saya membutuhkan ini pada distro centos lama DAN OSX serta Ubuntu.
edk750
lebih banyak jawaban terunggul unix.stackexchange.com/a/25378/5510
Trevor Boyd Smith
Apakah ada cara untuk memaksa buffer pipa / printf eksternal untuk proses yang sudah berjalan dengan PID dikenal?
Mvorisek
9

Anda dapat mencapai output buffered baris ke file dengan menggunakan scriptperintah seperti ini:

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
lebih tenang
sumber
-1 karena: a) tidak seperti jawaban yang diterima ini tidak berfungsi jika Anda ingin menjalankan perintah di latar belakang (perintah segera berakhir tanpa menyelesaikan batch_processjika Anda menambahkan &ke perintah di atas, setidaknya pada kotak Linux saya), yang tampaknya seperti kasus penggunaan yang sangat umum, dan b) tidak ada penjelasan di sini tentang cara kerja mantra ini.
Mark Amery
8

Di Ubuntu, paket unbufferprogram (dari expect-dev) melakukan trik untuk saya. Lari saja:

unbuffer your_command

dan itu tidak akan menahannya.

Calmarius
sumber
6

Solusi termudah yang saya temukan (tidak perlu paket pihak ketiga diinstal) disebutkan di utas serupa di situs Unix & Linux : gunakan scriptperintah. Ini sudah tua, dan kemungkinan sudah diinstal.

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

Perhatikan bahwa parameter nama file pertama untuk scriptperintah adalah file log yang akan ditulis . Jika Anda hanya menjalankan script -q your_command, Anda akan menimpa perintah yang Anda indentasi untuk dijalankan dengan file log. Periksa man script, agar aman, sebelum mencobanya.

Steve HHH
sumber
4

coba scriptperintahnya; jika sistem Anda memilikinya, dibutuhkan nama file sebagai argumen, semua teks yang dibuang ke stdout akan disalin ke file. Ini sangat berguna ketika program pengaturan membutuhkan interaksi.

Chris S
sumber
Saya tahu trik 'script -a out.txt'. Saya bertanya-tanya apakah ada cara lain untuk membuat proses penulisan tidak buffer.
James Dean
3

Secara pribadi saya lebih suka piping output dari perintah yang ingin saya periksa tee.

scriptmerekam terlalu banyak informasi, termasuk waktu penekanan tombol, dan banyak karakter yang tidak dapat dicetak. Apa yang teedisimpan lebih mudah dibaca oleh manusia untuk saya.

Paweł Brodacki
sumber
Saya juga akan menambahkan "| kurang" ke baris perintah.
HUB
4
Saya cukup yakin itu teedipengaruhi oleh buffering juga. Saya sering masih mendapatkan garis parsial yang ditampilkan oleh tee ketika memisahkan output dari findperintah.
Magellan
2

Redirect output ke file dan ikuti file dengan tail -fperintah.

Sunting

Jika ini masih mengalami buffering, maka gunakan fasilitas syslog (yang umumnya tidak terbaca). Jika proses batch berjalan sebagai skrip shell, Anda dapat menggunakan perintah logger untuk melakukan ini. Jika pekerjaan batch berjalan dalam bahasa scripting, harus ada fasilitas logging.

wolfgangsz
sumber
3
Ini adalah apa yang saya lakukan sekarang tetapi proses buffer menulis ke file dan itulah yang ingin saya hindari.
James Dean
Lihat hasil edit saya untuk proposal yang diperbarui.
wolfgangsz
1
Ini tidak berhasil karena alasan yang jelas. Siapa yang memberi This answer is usefuljawaban yang tidak berhasil, dan tidak mungkin bekerja?
cnst
1

Anda dapat menggunakan teeperintah, hanya sulap!

someCommand | tee logFile.logkeduanya akan ditampilkan di konsol dan menulis ke dalam file log.

Benj
sumber
Tidak bekerja teetidak akan menghentikan buffering dari terjadi.
cnst
1
@ cnst Secara efektif, teetidak akan menghindari beberapa buffering tetapi hanya akan memungkinkan Anda untuk melihat apa outputnya. Inilah yang diinginkan @JamesDean (karena saya tidak mengerti pertanyaannya), tapi saya pikir buffering sebenarnya bukan masalah di sini. Jika Anda memiliki detail lebih lanjut, beri tahu saya.
Benj
Dia ingin melihat output, dan dia tidak mendapatkan output apa pun (dengan cara yang tidak terganggu), namun Anda menyarankan untuk menggunakan teeuntuk mendapatkan tampilan yang lebih baik pada output yang tidak didapat?
cnst
1
Bagaimana saya merah pertanyaan @JamesDean: "Saya redirect ke output ke file '> out.txt'" berarti bagi saya tidak ada output konsol, tunggu proses untuk menyelesaikan sementara seluruh output diarahkan. Saat Anda menggunakan, >Anda tidak melihat apa pun di konsol. Saya kira @JamesDean menggunakan kata "buffering" untuk menggambarkan itu. Saya akan mengirim komentar pada pertanyaannya untuknya mengatakan lebih banyak tentang apa yang dia inginkan.
Benj