tail
25 GB'lık bir textfile istiyorsanız , tail
komut 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.
tail
25 GB'lık bir textfile istiyorsanız , tail
komut 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:
Hayır, tail
dosyanı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 -f
seç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 +linenumber
sözdizimi ya da tail +linenumber
desteklendiğinde standart olmayan bir seçenek kullanıldığında tail
, tüm dosyayı (kesilmediği sürece) açıkça okur.
tail +n
tüm dosyayı okuyacaktır - önce istenen yeni satır sayısını bulmak, sonra geri kalanını çıkarmak için.
tail
uygulamaların bunu yapmadığını veya doğru şekilde yapmadığını unutmayın. Örneğin busybox 1.21.1 tail
bu bakımdan bozuldu. Ayrıca, davranışın tail
stdin 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
)
tail
Kendin nasıl çalıştığını görebilirdin. Dosyalarımdan read
biri 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
strace
Çalıştırıldığında sistem çağrılarının tail
ne 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, lseek
okuyacağınız konumları ve read
sadece okur ve görebildiğiniz gibi kaç bayt okunduğunu gösterir,
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, tail
sadece 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 tail
bildiğ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.
Eğer head
yoksa 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 N
ilk / son N bayt yazdırmak için kullanabilirsiniz , ancak ne yazık ki bu bir POSIX özelliği değildir.
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. */