การเปลี่ยนเส้นทางเอาต์พุตไปยังไฟล์ใช้การล็อกไฟล์หรือไม่?


30

ถ้าฉันมีคำสั่ง

$ ./script >> file.log

ที่ถูกเรียกสองครั้งเมื่อมีสายที่สองเกิดขึ้นก่อนที่สายแรกจะจบลงจะเกิดอะไรขึ้น

การโทรครั้งแรกจะได้รับการล็อคแบบเอกสิทธิ์เฉพาะบุคคลในไฟล์เอาต์พุตหรือไม่? หากเป็นเช่นนั้นสคริปต์ที่สองจะล้มเหลวเมื่อพยายามเขียนหรือเชลล์ยอมรับเอาต์พุต (อนุญาตให้สคริปต์จบ) และส่งข้อผิดพลาดหรือไม่?

หรือไฟล์บันทึกถูกเขียนถึงสองครั้งหรือไม่?


1
ฉันไม่รู้ระบบที่จะล็อคไฟล์เป็นค่าเริ่มต้น สิ่งที่เป็นไปได้มากกว่าคือทั้งสองโปรแกรมจะจบการแทรกการเขียนเนื่องจากทั้งสองจะอยู่ในโหมดต่อท้าย ผลลัพธ์จะค่อนข้างคาดเดาไม่ได้ แทนที่จะเป็น "สวัสดีโลก" คุณจะได้รับ "hweolrllod"
jw013

คำตอบ:


18

เนื่องจากคุณใช้>>ซึ่งหมายถึงการผนวกแต่ละบรรทัดของเอาต์พุตจากแต่ละอินสแตนซ์จะถูกผนวกเข้าด้วยกันตามลำดับที่เกิดขึ้น

หากเอาต์พุตสคริปต์ของคุณพิมพ์ออกมา1\nโดย5\nมีการหน่วงเวลาหนึ่งวินาทีระหว่างแต่ละรายการและอินสแตนซ์ที่สองเริ่มต้นที่ 2.5 วินาทีในภายหลังคุณจะได้รับสิ่งนี้:

1
2
1
3
2
4
3
5
4
5

ดังนั้นเพื่อตอบคำถามของคุณ: ไม่


23

ระบบ Unix โดยและหลีกเลี่ยงการล็อคขนาดใหญ่ที่บังคับ มีบางกรณีที่เคอร์เนลจะล็อกไฟล์จากการดัดแปลงโดยโปรแกรมผู้ใช้ แต่ไม่ใช่ถ้ามันถูกเขียนโดยโปรแกรมอื่น ไม่มีระบบยูนิกซ์ที่จะล็อคไฟล์เพราะโปรแกรมกำลังเขียนลงไฟล์

หากคุณต้องการกรณีพร้อมกันสคริปต์ของคุณไม่ให้ดอกยางบนเท้าของแต่ละคนอื่นคุณจะต้องใช้กลไกการล็อคอย่างชัดเจนเช่นflock lockfile

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

สิ่งที่ไม่ดีที่อาจเกิดขึ้นคือถ้าหนึ่งในอินสแตนซ์เขียนหลายชิ้นของผลลัพธ์และคาดว่าจะออกมาพร้อมกัน ระหว่าง consecutives ที่เขียนโดยอินสแตนซ์หนึ่งอินสแตนซ์อื่นอาจทำการเขียนของตนเอง ตัวอย่างเช่นถ้าเช่น 1 เขียนfooแล้วเช่น 2 เขียนhelloและเพียงแล้วเช่น 2 เขียนแล้วไฟล์จะประกอบด้วยbarfoohellobar

กระบวนการเขียนไปยังไฟล์อย่างมีประสิทธิภาพเมื่อเรียกการwriteเรียกระบบ การเรียกใช้writeคือ atomic: การเรียกแต่ละครั้งเพื่อwriteเขียนลำดับของไบต์ที่จะไม่ถูกขัดจังหวะโดยโปรแกรมอื่น มักจะมีข้อ จำกัด เกี่ยวกับปริมาณข้อมูลที่การเรียกครั้งเดียวที่writeจะเขียนได้อย่างมีประสิทธิภาพ: สำหรับขนาดที่ใหญ่กว่าเฉพาะจุดเริ่มต้นของข้อมูลที่ถูกเขียนและแอปพลิเคชันจะต้องโทรwriteอีกครั้ง นอกจากนี้หลายโปรแกรมยังทำการบัฟเฟอร์: พวกเขาสะสมข้อมูลในพื้นที่หน่วยความจำแล้วเขียนข้อมูลนี้ในก้อนเดียว บางโปรแกรมล้างบัฟเฟอร์การส่งออกหลังจากบรรทัดที่สมบูรณ์หรือการแยกที่มีความหมายอื่น ๆ ด้วยโปรแกรมดังกล่าวคุณสามารถคาดหวังว่าทั้งบรรทัดจะไม่ถูกขัดจังหวะตราบใดที่มันไม่ยาวเกินไป (ไม่เกินสองสามกิโลไบต์ขึ้นอยู่กับระบบปฏิบัติการ) หากโปรแกรมไม่ได้ล้างข้อมูลที่จุดที่มีความหมาย แต่ขึ้นอยู่กับขนาดบัฟเฟอร์คุณอาจเห็นสิ่งต่าง ๆ เช่น 4kB จากอินสแตนซ์หนึ่งจากนั้น 4kB จากอินสแตนซ์อื่นจากนั้นอีก 4kB จากอินสแตนซ์แรกเป็นต้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.