Pipa bernama buffered non-blocking?

20

Saya mencari sesuatu yang saya curigai tidak ada: Pipa bernama buffered (fifo) non-blocking untuk digunakan dari baris perintah. Apakah ada hal seperti itu?

Inilah kasus penggunaannya: Misalkan saya memiliki proses yang akan berjalan lama di latar belakang dan memuntahkan banyak output stdout. Saya tidak terlalu peduli dengan output dan tidak ingin menyimpannya (mungkin saya tidak punya cukup ruang), tetapi saya ingin "mampir" secara berkala dan mengikuti apa yang dilakukannya, lalu keluar lagi dan biarkan untuk melakukan tugasnya. Jadi saya ingin mengarahkan outputnya ke pipa bernama buffered, non-blocking dan kemudian secara berkala menyadapnya.

Jadi pada dasarnya saya ingin memulai seperti ini ( 10Mmenjadi ukuran buffer):

mkmagicfifo magicfifo 10M
spewingprocess > magicfifo &

... dan secara berkala mampir untuk melihat apa yang terjadi ...

tail -f magicfifo

... tanpa magicfifo menyimpan semua output (jadi, bukan file normal), dan tanpa itu memblokir proses memuntahkan ketika mengisi dan tidak mengetuk (jadi, tidak cukup pipa bernama normal).

Saya tidak berpikir solusi yang melibatkan tailatau pruneakan melakukannya (well, saya bisa memikirkan solusi yang melibatkan tail), karena tailmasih akan mengharuskan saya menyimpan semua data di suatu tempat (jika saya ingin mampir dan keluar dari melihat itu), dan pruneharus menulis ulang file, mungkin (saya akui saya belum mencoba / membuktikan ini) melanggar pengalihan proses menghasilkan semua output.

Saya berharap saya dapat menulis beberapa utilitas untuk melakukan ini, tetapi * nix memiliki begitu banyak aspek keren dari file dan pipa dan semacamnya, saya hanya bisa berpikir ini ada dan saya tidak tahu tentang itu.

Jadi: Apakah ada hal seperti itu, dan jika demikian apa itu?

TJ Crowder
sumber
1
Apa yang Anda gambarkan adalah "buffer cincin" atau "buffer bundar". Saya tidak mengetahui adanya alat baris perintah untuk mempertahankan hal seperti itu, meskipun itu akan sepele untuk dibuat.
Shawn J. Goff
2
Lihat solusi yang dijelaskan dalam "Linux non-blocking fifo (on demand logging)", stackoverflow.com/questions/7360473/… .
1
Sepertinya ini telah diselesaikan di StackOverflow: stackoverflow.com/questions/7360473/…
James Blackburn
@ JamesBlackburn: Terima kasih! Sangat menarik.
TJ Crowder

Jawaban:

16

Saya pikir yang Anda cari adalah GNU screen. Ini mempertahankan buffer untuk menahan layar terakhir penuh atau dua output dari satu atau lebih program dan memungkinkan Anda memutuskan sambungan dan kembali lagi nanti.

psusi
sumber
+1 untuk layar saran. BTW, Anda dapat mengkonfigurasinya untuk menampung banyak "garis sejarah".
Tuan Shunz
1
Terima kasih. Bisakah Anda memberikan contoh bagaimana Anda akan menerapkannya pada perintah yang saya tunjukkan dalam pertanyaan saya? Halaman manual mengatakan itu adalah manajer jendela (saya pikir mereka maksud dalam arti terminal, bukan arti grafis, tapi tetap saja). Dan apakah saya masih bisa drop (via ssh) dan drop out seperlunya? (Misalnya, ops pada server jarak jauh.)
TJ Crowder
Ya, Anda dapat menggunakan layar GNU dengan cara ini. Anda akan membuat sesi baru (berpotensi bernama), menjalankan perintah Anda di dalam sesi itu, dan kemudian memutuskan sambungan.
TML
2
Ada juga tmuxdan dtach- apa pun di kelas yang sama dari aplikasi terminal multiplexer / sesi manajer harus dapat mencapai hal yang sama.
jw013
5

Anda dapat menggunakannya pv, ia menyediakan buffering sebanyak yang Anda inginkan dalam sebuah pipa. Anda bisa menggunakannya seperti ini:

sprewingprocess | pv -B 1g > ordinaryfifo &

Itu akan memberi Anda hingga 1GB buffering antara spewingprocessdan fifo. Sebagian besar distribusi Linux menawarkan pvpaket yang disebut, percaya atau tidak pv,.

David Schwartz
sumber
Terima kasih, tetapi bukankah itu akan memblokir begitu buffer penuh jika saya tidak membaca target bernama pipa?
TJ Crowder
1
Ya, tetapi pilihan apa yang Anda miliki? Di alam semesta yang terbatas, Anda tidak dapat memiliki buffering yang benar-benar tidak terbatas.
David Schwartz
Pilihan lain adalah seperti yang saya jelaskan dalam pertanyaan saya: Tidak menyimpan semua output. Ketika buffer sudah penuh, barang-barang tertua dibuang.
TJ Crowder
Hmm, saya menguji ini dan sayangnya tidak sepenuhnya berfungsi. Jika proses membaca fifo berhenti membaca untuk sementara waktu, pv memblokir mencoba menulis ke fifo, dan karena itu tidak multithreaded, itu juga memblokir membaca data ke dalam buffer pv. Jadi buffer pv hanya akan terus mengisi sementara proses membaca fifo terus membaca. pv mungkin dapat membaca dan buffer beberapa data, tetapi itu tidak menghalangi penulis untuk memblokir seluruhnya.
Daniel S. Sterling
1

Saya memiliki masalah yang sama. Ini solusi pertama saya. Pertama-tama tulis output ke file yang kita potong setelah setiap baris sehingga tidak tumbuh tanpa batas:

spewingprocess | while read line; do echo $line > buffer.txt ; done

Kemudian baca dari file menggunakan tail (di mana 2> /dev/nullmenghilangkan pesan kesalahan "file terpotong"):

tail -f ./buffer.txt 2> /dev/null

Dengan cara ini buffer tidak tumbuh dan kita dapat multiplex, mis. Jalankan sebanyak ekor yang kita inginkan. Namun, masalah dengan pendekatan ini adalah kita bisa kehilangan data saat kita memotong lebih cepat daripada yang bisa dibaca oleh ekor seperti yang ditunjukkan tes ini:

for ((i=0; ; i++)) ; do echo "$i" ; done | while read line; do  echo $line > buffer.txt ; done
tail -f ./buffer.txt 2> /dev/null > log.txt

Setelah berjalan beberapa saat, baris pertama dan terakhir adalah:

$ head -n 1 log.txt
0
$ tail -n 1 log.txt
78783

Tetapi file memiliki lebih sedikit baris, sehingga beberapa hilang:

$ wc log.txt
67087  67087 392819 log.txt

Tetap ini tampaknya solusi yang bagus jika Anda tidak terlalu peduli dengan kehilangan data atau ketika proses memuntahkan Anda tidak cukup cepat untuk kehilangan data terjadi.

bterwijn
sumber