หากฉันต้องการtail
ไฟล์ข้อความ 25 GB tail
คำสั่งจะอ่านไฟล์ทั้งหมดหรือไม่
เนื่องจากไฟล์อาจกระจายอยู่ในดิสก์ฉันคิดว่ามันมี แต่ฉันไม่เข้าใจ internals ดี
หากฉันต้องการtail
ไฟล์ข้อความ 25 GB tail
คำสั่งจะอ่านไฟล์ทั้งหมดหรือไม่
เนื่องจากไฟล์อาจกระจายอยู่ในดิสก์ฉันคิดว่ามันมี แต่ฉันไม่เข้าใจ internals ดี
คำตอบ:
ไม่มีtail
ไม่ได้อ่านไฟล์ทั้งหมดก็พยายามที่จะสิ้นสุดแล้วอ่านบล็อกถอยหลังจนถึงจำนวนที่คาดหวังของสายได้รับมาถึงแล้วก็จะแสดงเส้นในทิศทางที่ถูกต้องจนกว่าจะสิ้นสุดของแฟ้มและอาจจะยังคงตรวจสอบ ไฟล์ถ้าใช้-f
ตัวเลือก
อย่างไรก็ตามโปรดทราบว่าtail
ไม่มีทางเลือกนอกจากอ่านข้อมูลทั้งหมดหากมีการป้อนข้อมูลที่ไม่สามารถค้นหาได้เช่นเมื่ออ่านจากไปป์
ในทำนองเดียวกันเมื่อถูกขอให้ค้นหาบรรทัดที่เริ่มต้นจากจุดเริ่มต้นของไฟล์ด้วยการใช้tail -n +linenumber
ไวยากรณ์หรือtail +linenumber
ตัวเลือกที่ไม่ได้มาตรฐานเมื่อได้รับการสนับสนุนtail
อย่างชัดเจนอ่านไฟล์ทั้งหมด (เว้นแต่ถูกขัดจังหวะ)
tail +n
จะอ่านไฟล์ทั้งหมด - ก่อนอื่นเพื่อค้นหาจำนวนบรรทัดใหม่ที่ต้องการจากนั้นจึงส่งออกส่วนที่เหลือ
tail
การใช้งานไม่ทั้งหมดทำหรือทำอย่างถูกต้อง ตัวอย่างเช่น busybox 1.21.1 tail
นั้นใช้งานไม่ได้ นอกจากนี้โปรดทราบว่าพฤติกรรมจะแตกต่างกันเมื่อtail
ing stdin และที่ stdin เป็นไฟล์ปกติและตำแหน่งเริ่มต้นในไฟล์ไม่ได้อยู่ที่จุดเริ่มต้นเมื่อtail
มีการเรียกใช้ (เช่นใน{ cat > /dev/null; tail; } < file
)
คุณจะได้เห็นวิธีการtail
ทำงานของตัวเอง อย่างที่คุณสามารถทำได้สำหรับหนึ่งในไฟล์ของฉันread
ทำสามครั้งและอ่านทั้งหมด 10K ไบต์โดยรวม:
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
แสดงสิ่งที่เรียกระบบtail
ทำเมื่อทำงาน introdaction บางอย่างเกี่ยวกับระบบการเรียกคุณสามารถอ่านได้ที่นี่en.wikipedia.org/wiki/System_call สั้น ๆ - เปิด - เปิดไฟล์และส่งคืนหมายเลขอ้างอิง (3 ในตัวอย่างนี้) lseek
ตำแหน่งที่คุณกำลังจะอ่านและread
เพิ่งอ่านและตามที่คุณเห็นว่ามันส่งคืนจำนวนไบต์ที่อ่านจำนวนหนึ่ง
เนื่องจากไฟล์อาจกระจายอยู่ในดิสก์ฉันคิดว่ามันต้อง [อ่านไฟล์ตามลำดับ] แต่ฉันไม่เข้าใจ internals ดังกล่าวดี
อย่างที่คุณรู้ตอนนี้tail
เพียงแค่หาจุดสิ้นสุดของไฟล์ (ด้วยการเรียกของระบบlseek
) และทำงานย้อนหลัง แต่ในคำพูดที่ยกมาข้างต้นคุณสงสัยว่า"หางรู้ได้อย่างไรว่าอยู่ที่ไหนในดิสก์เพื่อหาจุดสิ้นสุดของไฟล์"
คำตอบนั้นง่าย: หางไม่รู้ กระบวนการระดับผู้ใช้จะเห็นไฟล์เป็นสตรีมต่อเนื่องดังนั้นทุกคนtail
สามารถรู้ได้ว่าเป็นการออฟเซ็ตจากจุดเริ่มต้นของไฟล์ แต่ในระบบไฟล์ไฟล์ "inode" (รายการไดเรกทอรี) จะเชื่อมโยงกับรายการตัวเลขที่แสดงถึงตำแหน่งทางกายภาพของบล็อกข้อมูลของไฟล์ เมื่อคุณอ่านจากไฟล์เคอร์เนล / ไดรเวอร์อุปกรณ์จะเป็นตัวกำหนดว่าคุณต้องการส่วนใดทำงานอย่างไรตำแหน่งที่ตั้งของดิสก์และดึงข้อมูลให้คุณ
นั่นคือสิ่งที่เรามีระบบปฏิบัติการสำหรับ: ดังนั้นคุณไม่ต้องกังวลว่าบล็อกของไฟล์ของคุณจะกระจายอยู่ที่ไหน
หากhead
หรือtail
ดูเหมือนว่ากำลังอ่านไฟล์ทั้งหมดสาเหตุที่เป็นไปได้คือไฟล์นั้นมีอักขระขึ้นบรรทัดใหม่น้อยหรือไม่มีเลย ฉันสะดุดมากขึ้นเมื่อไม่กี่เดือนที่ผ่านมาด้วยหยดขนาดใหญ่ (กิกะไบต์) JSON ที่ต่อเนื่องกันโดยไม่มีช่องว่างใด ๆ เลยแม้แต่ในสาย
หากคุณมีหัว / หาง GNU คุณสามารถใช้-c N
เพื่อพิมพ์ N ไบต์แรก / สุดท้ายแทนเส้นแต่น่าเสียดายที่นี่ไม่ใช่คุณสมบัติ POSIX
อย่างที่คุณเห็นในซอร์สโค้ดบรรทัด 525 คุณสามารถเห็นข้อคิดเห็นสำหรับการนำไปใช้งาน
/* 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. */