ทำไม tar ดูเหมือนจะข้ามเนื้อหาไฟล์เมื่อไฟล์ที่ส่งออกเป็น / dev / null?


21

ฉันมีไดเรกทอรีที่มีข้อมูลมากกว่า 400 GiB ฉันต้องการตรวจสอบว่าไฟล์ทั้งหมดสามารถอ่านได้โดยไม่มีข้อผิดพลาดดังนั้นวิธีที่ง่าย ๆ ที่ฉันคิดก็คือการนำtarไป/dev/nullใช้ แต่ฉันกลับเห็นพฤติกรรมต่อไปนี้แทน:

$ time tar cf /dev/null .

real    0m4.387s
user    0m3.462s
sys     0m0.185s
$ time tar cf - . > /dev/null

real    0m3.130s
user    0m3.091s
sys     0m0.035s
$ time tar cf - . | cat > /dev/null
^C

real    10m32.985s
user    0m1.942s
sys     0m33.764s

คำสั่งที่สามด้านบนถูกบังคับให้หยุดโดยCtrl+ Cหลังจากรันมานานแล้ว ยิ่งไปกว่านั้นในขณะที่คำสั่งสองคำสั่งแรกที่ใช้งานได้ตัวบ่งชี้กิจกรรมของอุปกรณ์เก็บข้อมูลที่มี.อยู่นั้นไม่ได้ทำงาน ด้วยคำสั่งที่สามตัวบ่งชี้จะสว่างขึ้นอย่างต่อเนื่องหมายถึงยุ่งมาก

ดังนั้นดูเหมือนว่าเมื่อtarสามารถค้นพบว่าไฟล์ที่ส่งออกของมัน/dev/nullคือเมื่อ/dev/nullเปิดโดยตรงที่จะมีการจัดการไฟล์ที่tarเขียนไปแล้วร่างกายของไฟล์จะปรากฏขึ้นข้าม (การเพิ่มvตัวเลือกในการtarพิมพ์ไฟล์ทั้งหมดในไดเรกทอรีเป็นtar'สีแดง)

ดังนั้นฉันสงสัยว่าทำไมจึงเป็นเช่นนี้? มันเป็นการเพิ่มประสิทธิภาพบางอย่าง? ถ้าใช่แล้วทำไมtarถึงต้องการเพิ่มประสิทธิภาพที่น่าสงสัยสำหรับกรณีพิเศษเช่นนั้น?

ฉันใช้ GNU tar 1.26 กับ glibc 2.27 บน Linux 4.14.105 amd64


7
find . -type f -exec shasum -a256 -b '{}' +ในฐานะที่เป็นทางเลือกที่พิจารณาสิ่งที่ต้องการ ไม่เพียง แต่จะจริงอ่านและการตรวจสอบข้อมูลทั้งหมด แต่ถ้าคุณเก็บเอาท์พุทที่คุณสามารถ re-run ในภายหลังเพื่อตรวจสอบว่าเนื้อหาของไฟล์ที่ไม่ได้เปลี่ยนแปลง
Ilmari Karonen

ในการวัดสิ่งที่คุณยังสามารถใช้:pv tar -cf - | pv >/dev/nullนั่นก้าวย่างปัญหาและให้ข้อมูลความคืบหน้าแก่คุณ ( pvตัวเลือกต่าง ๆ)
xenoid

คุณมีฟีเจอร์มิสที่รู้จักกันดีของ GNU tar ใช้gtar -cf /dev/zero ...เพื่อให้ได้สิ่งที่คุณชอบ
schily

คำตอบ:


25

มันคือ การเพิ่มประสิทธิภาพการบันทึก :

เมื่อสร้างไฟล์เก็บถาวร/dev/nullGNU tar จะพยายามลดการดำเนินการอินพุตและเอาต์พุตให้น้อยที่สุด ระบบสำรองข้อมูล Amanda เมื่อใช้กับ GNU tar มีขนาดการปรับขนาดเริ่มต้นซึ่งใช้คุณสมบัตินี้


4
อานี่ไม่ได้อธิบายไว้ใน man page ที่ฉันติดตั้งไว้ ควรลองinfo tarแทน ...
Ruslan

9
พวกเขาควรทำให้หน้าข้อมูลมนุษย์ & ข้อมูลตรงกันตรงกันจริง ๆ แล้วเป็นข้อผิดพลาดที่พวกเขาไม่ได้
Xen2050

9
@Ruslan ด้วยยูทิลิตี้ GNU ส่วนใหญ่หน้า man จะมีข้อมูลสรุปสั้น ๆ เท่านั้นโดยทั่วไปจะดีพอเมื่อคุณจำได้ว่ามันมีตัวเลือกให้ทำอะไร แต่จำชื่อตัวเลือกไม่ได้ เอกสารที่สมบูรณ์อยู่ในรูปแบบที่ไม่สามารถแปลได้ดีกับ man pages และสามารถใช้ได้กับinfoหรือเป็น HTML ในเบราว์เซอร์
Gilles 'หยุดความชั่วร้าย'

18
มันเป็นปัญหาที่ได้รับการยอมรับ
โอเว่น

8

นี้สามารถเกิดขึ้นความหลากหลายของโปรแกรมด้วยตัวอย่างเช่นผมมีพฤติกรรมที่ครั้งเดียวเมื่อเพียงแค่ใช้cp file /dev/null; แทนที่จะได้รับความเร็วในการอ่านดิสก์โดยประมาณคำสั่งจะส่งคืนหลังจากผ่านไปไม่กี่มิลลิวินาที

เท่าที่ฉันจำได้นั่นคือบน Solaris หรือ AIX แต่หลักการนี้ใช้กับระบบ unix-y ทุกชนิด

ในสมัยก่อนเมื่อโปรแกรมคัดลอกไฟล์ไปที่อื่นมันจะสลับกันระหว่างการreadโทรที่รับข้อมูลบางอย่างจากดิสก์ (หรืออะไรก็ตามที่ไฟล์ descriptor อ้างถึง) ไปยังหน่วยความจำ (พร้อมรับประกันทุกอย่างที่นั่นเมื่อreadส่งคืน) และการwriteโทร (ซึ่งจะใช้หน่วยความจำและส่งเนื้อหาไปยังปลายทาง)

อย่างไรก็ตามมีวิธีที่ใหม่กว่าอย่างน้อยสองวิธีในการบรรลุเป้าหมายดังกล่าว:

  • Linux มีการเรียกของระบบcopy_file_range(ไม่สามารถพกพาไปยัง unixes อื่น ๆ ได้ทั้งหมด) และsendfile(ค่อนข้างพกพาได้ แต่เดิมตั้งใจจะส่งไฟล์ไปยังเครือข่าย แต่สามารถใช้ปลายทางได้ในขณะนี้) พวกเขาตั้งใจที่จะเพิ่มประสิทธิภาพการถ่ายโอน; หากโปรแกรมใช้หนึ่งในนั้นก็เป็นไปได้ที่เคอร์เนลจะจดจำเป้าหมายได้อย่างง่ายดาย/dev/nullและเปลี่ยนการเรียกของระบบให้เป็นแบบไม่มีการปรั

  • โปรแกรมสามารถใช้mmapรับเนื้อหาไฟล์แทนreadโดยทั่วไปหมายถึง "ตรวจสอบให้แน่ใจว่าข้อมูลอยู่ที่นั่นเมื่อฉันพยายามเข้าถึงหน่วยความจำอันนั้น" แทนที่จะเป็น "ให้แน่ใจว่าข้อมูลอยู่ที่นั่นเมื่อระบบโทรกลับมา" ดังนั้นโปรแกรมสามารถmmapไฟล์ต้นฉบับจากนั้นเรียกใช้writeหน่วยความจำที่แมป อย่างไรก็ตามเนื่องจากการเขียน/dev/nullไม่จำเป็นต้องเข้าถึงข้อมูลที่เป็นลายลักษณ์อักษรเงื่อนไข "ตรวจสอบให้แน่ใจว่ามี" ไม่เคยถูกเรียกใช้ทำให้ไฟล์ไม่ได้ถูกอ่าน

ไม่แน่ใจว่า gnu tar ใช้สิ่งใดและกลไกสองอย่างนี้เมื่อตรวจพบว่ามันกำลังเขียน/dev/nullหรือไม่ แต่เป็นเหตุผลว่าทำไมโปรแกรมใด ๆเมื่อใช้ในการตรวจสอบความเร็วในการอ่านควรรันด้วย| cat > /dev/nullแทนที่จะเป็น> /dev/null- และทำไม| cat > /dev/nullควร จะหลีกเลี่ยงได้ในกรณีอื่น ๆ


ฉันคิดว่าความหมายในtarหน้าข้อมูลGNU (ดูคำตอบอื่น ๆ ) คือมันมีโหมดพิเศษสำหรับสิ่งนี้ซึ่งน่าจะเป็นเพียงไฟล์สถิติโดยไม่ต้องเปิด ในความเป็นจริงฉันเพิ่งตรวจสอบกับtar cf /dev/null foo*ไฟล์คู่และใช่เพียงแค่newfstatat(..., AT_SYMLINK_NOFOLLOW)ระบบโทรไม่แม้แต่open()ที่อาจปรับปรุง atime แต่ +1 สำหรับการอธิบายกลไกที่สามารถเกิดขึ้นได้โดยไม่ต้องตรวจจับเป็นพิเศษ
Peter Cordes

คำอธิบาย mmap ควรอ่าน "เข้าถึงข้อมูลที่อ่าน " แทนที่จะ "เข้าถึงข้อมูลที่เขียนหรือไม่"
Wayne Conrad

ดูเพิ่มเติมsplice(2)ที่ Linux ที่จริงแล้วการแทนที่cat > /dev/nullด้วยpv -q > /dev/null(ซึ่งใช้splice()กับ Linux) น่าจะลดค่าใช้จ่าย หรือdd bs=65536 skip=9999999999 2> /dev/nullหรือwc -c > /dev/nullหรือtail -c1 > /dev/null...
Stéphane Chazelas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.