Mengapa perintah berikut tidak menghasilkan output apa pun?
$ tail -f /etc/passwd | tail
Setelah membaca tentang buffering , saya mencoba yang berikut ini tetapi tidak berhasil:
$ tail -f /etc/passwd | stdbuf -oL tail
Perhatikan bahwa yang berikut ini menghasilkan output:
$ tail /etc/passwd | tail
Begitu juga ini:
$ tail -f /etc/passwd | head
Saya menggunakan versi ekor 8.21 (GNU coreutils).
Jawaban:
Saya pikir saya telah melihat semuanya di UNIX. Pertanyaan ini menampar saya dari keangkuhan saya. Pertanyaan yang sangat bagus!
tail
menunjukkan garis X terakhir.tail -f
melakukan hal yang sama, tetapi pada dasarnya dalam loop tak terbatas: saat start-up, tunjukkan baris X terakhir dari file, kemudian gunakan beberapa keajaiban OS (seperti inotify), monitor dan tampilkan baris baru.Untuk melakukan tugasnya,
tail
harus dapat menemukan akhir file. Jikatail
tidak dapat menemukan ujung file, itu tidak dapat menunjukkan garis X terakhir, karena "terakhir" tidak ditentukan. Jadi apa yangtail
dilakukan dalam kasus ini? Itu menunggu sampai menemukan akhir file.Pertimbangkan ini:
Ini sepertinya tidak pernah membuat kemajuan, karena tidak pernah ada akhir file yang pasti
chatter
.Anda mendapatkan perilaku yang sama jika Anda meminta
tail
untuk memberikan baris terakhir dari pipa sistem file. Mempertimbangkan:stdbuf
untuk mengatasi masalah yang dirasakan adalah upaya mulia. Fakta kuncinya adalah bahwa buffering I / O bukanlah penyebab utama: tidak adanya end-of-file yang pasti. Jika Anda memeriksa kode sumber tail.c , Anda akan melihatfile_lines
komentar fungsi berbunyi:dan itulah keajaibannya. Anda memerlukan end-of-file agar tail dapat berfungsi dalam konfigurasi apa pun.
head
tidak memiliki batasan itu, hanya perlu memulai file (yang mungkin tidak, cobahead test.pipe
). Alat berorientasi aliran sukased
danawk
tidak membutuhkan awal atau akhir file: mereka bekerja pada buffer.sumber
tail -f
Ekor sebenarnya adalah sesuatu yang tidak diketahui di masa sekarang, jadi bagaimana seharusnya yang berikutnyatail
tahu itu. Di sisi laintail -f
kepala adalah sesuatu yang sudah diketahui dan bisa diproses.Atau untuk membuatnya lebih sederhana:
tail
relatif terhadap akhir file, tetapi aliran outputtail -f
tidak mendapat EOF (setidaknya tidak sebelum terminasi).Jika Anda menemukan pertama
tail
's pid dan membunuhnya, Anda harus kemudian melihat output dari kedua.sumber
Jawaban teknis
Ketika berjalan dengan stream sebagai input,
tail
simpann
buffer-line yang terisi saat membaca stream, tetapi ia tidak dapat menampilkan baris-baris itu sampai mencapai akhir stream, yaitu ia menerimaEOF
kode khusus ketika mencoba membaca dari input aliran. Doatail -f
tidak keluar, sehingga ia tidak akan pernah menutup alirannya, yang membuatnya tidak mungkin misalnya mengembalikan 10 baris terakhir dari aliran itu.sumber
Fungsi
tail
adalah untuk menunjukkan bagian terakhir - "ekor" - dari input atau file. (Pilihannya-f
adalah tentang apa yang dikerjakannya nanti, jadi itu tidak relevan di sini.)Mari kita pikirkan sebuah file:
Apa bagian terakhir dari file ?
Katakanlah itu adalah n baris terakhir file.
Ketika kita membaca baris
i
file input, bagaimana memutuskannya perlu dicetak atau tidak?Kami tidak tahu apakah itu di bagian terakhir - karena kami tidak tahu yang mana baris terakhir. Jadi kita tidak bisa mencetaknya sekarang.
Kita perlu menjaga garis sampai menjadi jelas bahwa itu adalah bagian dari
n
baris terakhir , atau tidak dapat lagi menjadi bagian dari itu, karena kita tahun
garis lebih lanjutJika sekarang kita sampai pada akhir file , kita tahu bahwa
n
baris terakhir yang kita simpan sebenarnya adalahn
baris terakhir file.Sekarang, dalam kasus
yang pertama
tail
membaca file, dan kemudian menunggu untuk mendapatkan lebih banyak data darinya, untuk menuliskannya juga. Jadi itu tidak akan menandakan ujung file ke ekor kedua ketika sampai ke ujung file yang dibacanya. Tanpa itu, yang keduatail
tidak pernah diberitahu tentang akhir file, sehingga tidak akan pernah tahu baris mana yang harus dicetak.sumber