Kuyruk tüm dosyayı okur mu?


113

tail25 GB'lık bir textfile istiyorsanız , tailkomut tüm dosyayı okuyor mu?

Bir dosya bir diske dağılmış olabileceğinden, bunu yapmak zorunda olduğunu hayal ediyorum, ancak bu kadar iç işlemi iyi anlamadım.

Yanıtlar:


119

Hayır, taildosyanın tamamını okumaz, sonuna kadar arar, ardından beklenen satır sayısına ulaşılana kadar blokları geriye doğru okur, ardından satırları dosyanın sonuna kadar doğru yönde görüntüler ve muhtemelen dosyayı izlemeye devam eder -fseçenek kullanılırsa dosya .

Bununla birlikte, tailörneğin bir borudan okuma yaparken, aranamayan bir giriş sağlanmışsa tüm verileri okumaktan başka seçeneğinin olmadığını unutmayın .

Benzer şekilde, dosya başlangıcından başlayarak satırları aramanız istendiğinde, tail -n +linenumbersözdizimi ya da tail +linenumberdesteklendiğinde standart olmayan bir seçenek kullanıldığında tail, tüm dosyayı (kesilmediği sürece) açıkça okur.


14
Kahretsin, çok hızlı :-). İşte ilgili kaynak kodu . FD dosyasının sonundan son N_LINES satırını yazdır. Dosyanın başlangıcına gelinceye veya NUMBER yeni satırları okuyana kadar bir seferde 'BUFSIZ' baytını (muhtemelen ilk hariç) okuyarak dosyaya geri gidin.
Patrick

1
Ayrıca, tail +ntüm dosyayı okuyacaktır - önce istenen yeni satır sayısını bulmak, sonra geri kalanını çıkarmak için.
SF.

@SF. Gerçekten, cevap güncellendi.
jlliagre

4
Tüm tailuygulamaların bunu yapmadığını veya doğru şekilde yapmadığını unutmayın. Örneğin busybox 1.21.1 tailbu bakımdan bozuldu. Ayrıca, davranışın tailstdin ve stdin'in normal bir dosya olduğu durumlarda değiştiğini ve dosyadaki ilk konumun tailçağrıldığında başlangıçta olmadığını unutmayın (içinde olduğu gibi { cat > /dev/null; tail; } < file)
Stéphane Chazelas

4
@StephaneChazelas * nix - garip kenar vakalarının dünyası normalleşiyor. (Non-seekable girişler vs aranabilir olsa kesinlikle geçerli bir noktadır.)
Bir CVn

69

tailKendin nasıl çalıştığını görebilirdin. Dosyalarımdan readbiri için yapabileceğiniz gibi üç kez yapılır ve toplamda yaklaşık 10K bayt okunur:

strace 2>&1  tail ./huge-file >/dev/null  | grep -e "read" -e "lseek" -e "open" -e "close"
open("./huge-file", O_RDONLY)           = 3
lseek(3, 0, SEEK_CUR)                   = 0
lseek(3, 0, SEEK_END)                   = 80552644
lseek(3, 80551936, SEEK_SET)            = 80551936
read(3, ""..., 708) = 708
lseek(3, 80543744, SEEK_SET)            = 80543744
read(3, ""..., 8192) = 8192
read(3, ""..., 708) = 708
close(3)                                = 0

Bunun soruyu nasıl cevapladığını anlamıyorum. Burada neler olduğunu açıklayabilir misin?
Iain Samuel McLean Elder

10
straceÇalıştırıldığında sistem çağrılarının tailne yaptığını gösterir . Sistem çağrılarıyla ilgili bazı bilgiler burada en.wikipedia.org/wiki/System_call adresini okuyabilirsiniz . Kısaca - açık - bir dosyayı açar ve bir tutamacı (bu örnekte 3) döndürür, lseekokuyacağınız konumları ve readsadece okur ve görebildiğiniz gibi kaç bayt okunduğunu gösterir,
Sergei Kurenkov

2
Böylece sistem çağrılarını analiz etmek bazen bir programın nasıl çalıştığını anlayabilirsiniz.
Sergei Kurenkov

26

Bir dosya bir diske dağılmış olabileceğinden, [dosyayı sırayla okumak zorunda] olduğunu hayal ediyorum, ancak bu tür içselleri iyi anlamıyorum.

Şimdi bildiğiniz gibi, tailsadece dosyanın sonuna bakar (sistem çağrısı ile lseek) ve geriye doğru çalışır. Ancak, yukarıda belirtilen açıklamada, "kuyruğun dosyanın sonunu nerede bulacağını nerden biliyor?"

Cevap basit: Kuyruk bilmiyor. Kullanıcı düzeyinde süreçler, dosyaları sürekli akışlar olarak görür, bu nedenle herkesin tailbildiği gibi, dosyanın başlangıcından itibaren ofset olduğu bilinir. Ancak, dosya sisteminde, dosyanın "inode" si (dizin girişi), dosyanın veri bloklarının fiziksel konumunu belirten bir sayı listesi ile ilişkilidir. Dosyadan okuduğunuzda, çekirdek / aygıt sürücüsü ihtiyacınız olan kısmı belirler, diskteki konumunu belirler ve sizin için alır.

Bu bizim işletim sistemimiz için geçerli olan şey. Bu nedenle, dosyanızın bloklarının nereye dağıldığına dair endişelenmenize gerek yok.


2

Eğer headyoksa tail görünür dosyanın tamamını okumak zorunda, olası bir nedeni olduğunu dosya az veya hiç satır karakterler içeriyor . Birkaç ay önce, herhangi bir boşluk bırakmadan serileştirilmiş çok sayıda (gigabayt) JSON bloğu ile takıldım.

GNU kafa / kuyruk varsa, satırlar yerine -c Nilk / son N bayt yazdırmak için kullanabilirsiniz , ancak ne yazık ki bu bir POSIX özelliği değildir.


1

Eğer görebileceğiniz gibi kaynak kod hattı 525, sen uygulanması için yorumları görebilir.

 /* Print the last N_LINES lines from the end of file FD.
   Go backward through the file, reading 'BUFSIZ' bytes at a time (except
   probably the first), until we hit the start of the file or have
   read NUMBER newlines.
   START_POS is the starting position of the read pointer for the file
   associated with FD (may be nonzero).
   END_POS is the file offset of EOF (one larger than offset of last byte).
   Return true if successful.  */
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.