Masuk melalui FIFO, lalu redirect ke file?

8

Saya memiliki aplikasi yang harus mencatat setiap transaksi. Setiap pesan log memerah karena kita harus memiliki catatan tentang apa yang terjadi sebelum terjadi kerusakan. Rekan-rekan saya dan saya ingin tahu tentang cara mencapai efek kinerja buffering sambil menjamin bahwa pesan log telah meninggalkan proses.

Yang kami temukan adalah:

  • membuat FIFO yang dapat digunakan aplikasi untuk menulis, dan
  • mengarahkan isi FIFO itu ke file biasa via cat.

Yaitu, apa yang biasanya:

app --logfile logfile.txt

sekarang:

mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

Apakah ada gotcha untuk pendekatan ini? Ini berfungsi ketika kami mengujinya, tetapi kami ingin memastikan bahwa pesan akan menemukan jalannya ke file pengalihan bahkan jika aplikasi asli macet.

(Kami tidak memiliki kode sumber ke aplikasi, jadi solusi pemrograman tidak mungkin. Selain itu, aplikasi tidak akan menulis stdout, jadi mengirim langsung ke perintah yang berbeda tidak mungkin. Jadi syslogtidak mungkin .)


Pembaruan: Saya telah menambahkan hadiah. Jawaban yang diterima akan tidak melibatkan loggeruntuk alasan sederhana bahwa loggeradalah tidak apa yang saya bertanya tentang. Seperti yang dinyatakan dalam pertanyaan awal, saya hanya mencari gotcha dalam menggunakan FIFO.

chrisaycock
sumber
Tampaknya ada beberapa kebingungan besar dalam beberapa jawaban sejauh ini. Seperti yang awalnya saya soroti dalam pertanyaan saya, saya mencari gotcha dengan pendekatan menggunakan FIFO sebagai perantara logging . Saya tidak tertarik dengan saran alternatif yang setidaknya tidak mengeksplorasi Gotcha dari pertanyaan awal saya.
chrisaycock
Jika jawaban saya tentang masuk ke stdout bukanlah arah yang Anda minati, dapatkah Anda menghapus "Juga, aplikasi tidak akan menulis ke stdout, jadi mengirim langsung ke perintah yang berbeda tidak sesuai dengan pertanyaan" dari pertanyaan?
jamaah

Jawaban:

6

Perhatikan bahwa fifo biasanya diperlukan dalam pemrograman di mana jumlah yang ditulis dapat melebihi jumlah yang dibacakan.

Dengan demikian fifo tidak akan berfungsi sepenuhnya lancar seperti yang Anda harapkan tetapi akan menyelesaikan masalah utama Anda saat memperkenalkan yang lain.

Ada tiga kemungkinan peringatan.

  1. Menulis ke fifo diblokir tanpa batas jika tidak ada yang membaca ujung lainnya di inisialisasi.
  2. Fifo memiliki lebar tetap 64K dimana jika buffer diisi pada titik itu, penulisan selanjutnya akan diblokir sampai pembaca berhasil.
  3. Penulis pipa akan dibunuh dengan SIGPIPE jika pembaca meninggal atau keluar.

Ini berarti bahwa masalah Anda (meniru I / O buffer pada penulisan yang tidak buffer) akan diselesaikan. Itu karena 'batas' baru pada FIFO Anda akan berlaku menjadi kecepatan utilitas apa pun yang menulis apa yang ada di pipa ke disk (yang mungkin akan buffered I / O).

Namun demikian, penulis menjadi tergantung pada fungsi pembaca log Anda. Jika pembaca berhenti membaca dengan tiba-tiba, penulis akan memblokir. Jika pembaca tiba-tiba keluar (misalkan Anda kehabisan ruang disk pada target Anda) penulis akan SIGPIPE dan mungkin keluar.

Hal lain yang perlu disebutkan adalah jika server panik dan kernel berhenti merespons Anda mungkin kehilangan hingga 64 ribu data yang ada di buffer itu.

Cara lain untuk memperbaikinya adalah dengan menulis log ke tmpfs (/ dev / shm di linux) dan mengekor output ke lokasi disk tetap. Ada batasan yang kurang membatasi pada alokasi memori melakukan ini (bukan 64K, biasanya 2G!) Tetapi mungkin tidak bekerja untuk Anda jika penulis tidak memiliki cara dinamis untuk membuka kembali file log (Anda harus membersihkan log dari tmpfs secara berkala). Jika server panik dalam metode ini, Anda bisa kehilangan BANYAK lebih banyak data.

Matthew Ife
sumber
Itu beberapa info bagus tentang /dev/shm. Kami telah mempertimbangkan itu juga, meskipun itu telah menyelinap untuk digunakan tail -f.
chrisaycock
4
mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

Apa yang terjadi ketika cat logfifoproses Anda mati, seseorang membunuhnya secara tidak sengaja, atau seseorang secara tidak sengaja menunjuk ke lokasi yang salah?

Pengalaman saya adalah bahwa appakan dengan cepat memblokir dan menggantung. Saya sudah mencoba ini dengan Tomcat, Apache dan beberapa aplikasi homebuilt kecil, dan mengalami masalah yang sama. Saya tidak pernah menyelidiki terlalu jauh, karena loggeratau pengalihan I / O sederhana melakukan apa yang saya inginkan. Saya biasanya tidak membutuhkan kelengkapan pencatatan, yang ingin Anda kejar. Dan seperti yang Anda katakan, Anda tidak ingin logger.

Ada beberapa diskusi tentang masalah ini di Linux non-blocking fifo (on demand logging) .

Stefan Lasiewski
sumber
Menarik. Jadi aplikasi tetap bisa diblokir? Kami sedang berpikir untuk menyerah dan memesan Fusion IO pada titik ini.
chrisaycock
Cobalah. Bagi saya, hasil ini terjadi dengan cepat (dalam lingkungan uji pada perangkat keras spesifikasi rendah). Ini di Ubuntu dan RedHat 5. Tidak yakin apakah FreeBSD, dll. Memiliki perilaku serupa.
Stefan Lasiewski
2

Pilihan Anda dibatasi oleh aplikasi, tetapi apa yang telah Anda uji akan berhasil.

Kami melakukan sesuatu yang mirip dengan pernis dan varnishncsa dengan get log di suatu tempat yang berguna bagi kami. Kami memiliki fifo dan hanya membacanya dengan syslog-ng dan mengirimkannya ke tempat yang kami butuhkan. Kami menangani sekitar 50GB dan belum menemukan masalah dengan pendekatan ini sejauh ini

goo
sumber
Keren, senang mendengar kami bukan satu-satunya yang datang dengan ini.
chrisaycock
2

Lingkungan adalah CentOS dan aplikasi menulis ke file ...

Alih-alih mengirim ke file biasa, saya akan mengirim output ke syslog dan memastikan bahwa pesan syslog sedang dikirim ke server pusat dan juga secara lokal.

Anda harus dapat menggunakan skrip shell seperti ini:

logger -p daemon.notice -t app < fifo

Anda juga dapat mengambil input (ke logger) dari catatau dari tail -fke dalam pipa:

tail -f fifo | logger ...
cat fifo | logger ...

Satu-satunya masalah adalah bahwa ia tidak membedakan berdasarkan pentingnya pesan log (semuanya PEMBERITAHUAN ) tetapi setidaknya itu akan dicatat dan juga dikirim di-host ke server pusat.

Konfigurasi syslog tergantung pada server mana yang Anda gunakan. Ada rsyslogdan syslog-ng(keduanya sangat mampu).

EDIT : Direvisi setelah mendapatkan informasi lebih lanjut dari poster.

Mei
sumber
Pesan log ditulis ke file yang dapat kita pilih, tetapi aplikasi tidak mau menulis stdout. OSnya adalah CentOS (saya telah menandai pertanyaan sebagai linux , tapi saya rasa itu mudah untuk dilewatkan). Semua pesan sama pentingnya, sehingga tidak ada perbedaan antara pemberitahuan dan kesalahan dalam aplikasi ini.
chrisaycock
Tidak ada perbedaan antara pemberitahuan dan kesalahan? Oh benarkah ? Tidak ada perbedaan antara Slow query detecteddan Database halted?
Mei
(Aku diperbaharui pos.)
Mei
1

Anda menulis:

Selain itu, aplikasi tidak akan menulis ke stdout...

Apakah Anda mencoba masuk ke "file" /dev/stdout? Itu mungkin memungkinkan Anda untuk melakukan sesuatu seperti:

app --logfile /dev/stdout | logger -t app
pendatang
sumber
Apakah itu berbeda dari FIFO? Apa sajakah Gotcha? Saya tidak mencari alternatif, per se ; Saya mencari wawasan apakah pendekatan yang saya daftarkan kuat. Itu saja yang saya tertarik.
chrisaycock
1
Ya, ini berbeda dengan FIFO; itu pada dasarnya file yang terhubung ke STDOUT. Jadi Anda dapat menggunakannya untuk masuk ke STDOUT, dan dari sana ke syslog atau yang serupa. Ini dimaksudkan sebagai solusi untuk masalah awal Anda, tetapi semoga lebih kuat daripada FIFO karena memiliki lebih sedikit bagian yang bergerak.
jamaah
1

Tidak ada gunanya menulis ke fifo dan kemudian meminta proses lain menulisnya ke file. Cukup tulis langsung ke file secara normal dan begitu write()pengembaliannya, ada di tangan kernel; masih akan menulisnya ke disk jika aplikasi macet.

psusi
sumber
Setiap pesan log memerah : ini memblokir tulis. Kami tidak memiliki kendali atas itu karena kami tidak memiliki kode sumber aplikasi.
chrisaycock
@ chrisaycock, benar ... jadi di mana masalahnya?
psusi
Rekan-rekan saya dan saya ingin tahu tentang cara mencapai efek kinerja buffering sambil menjamin bahwa pesan log telah meninggalkan proses.
chrisaycock
@ chrisaycock, ohh, jadi aplikasi saat ini menggunakan O_SYNC atau fsync()untuk menunggu setiap penulisan mencapai disk, dan Anda TIDAK ingin itu terjadi (mempertaruhkan kerugian jika terjadi crash sistem)?
psusi
1
@ chrisaycock, ini tidak ada hubungannya dengan antarmuka drive, itu biasanya hanya berarti kernel telah menyalinnya ke cache sistem file (dan keluar dari aplikasi). Seperti yang saya katakan pada jawaban saya pada awalnya, setelah write()kembali, aplikasi dapat crash semua suka - data akan sampai ke disk selama kernel tidak crash.
psusi