ใช้ inotifywait พร้อมกับเสียงเรียกเข้า


14

ฉันมีสคริปต์ง่ายๆที่ตรวจสอบไฟล์สำหรับการเปลี่ยนแปลงและ rsyncs ด้วยสำเนาระยะไกล:

#!/bin/bash

while inotifywait -e close_write somefile
do
    rsync somefile user@host.domain:./somefile
done

มันใช้งานได้ดีกับนาโน แต่ล้มเหลวด้วยเสียงเรียกเข้า เมื่อฉันใช้ nano มันจะออกผลลัพธ์:

somefile CLOSE_WRITE,CLOSE   

และเริ่มวนรอบถัดไปรอรุ่นอื่น

เมื่อฉันใช้เป็นกลุ่มจะไม่มีผลลัพธ์สคริปต์จะปิดด้วยรหัสออก 0

ฉันทำการวิจัยบางอย่างและพบว่า close_write เป็นพารามิเตอร์ที่ถูกต้องสำหรับ uing initofywait พร้อมกับ vim (ตอนแรกฉันต้องการใช้เหตุการณ์แก้ไข) แต่ด้วยเหตุผลบางอย่างมันล้มเหลวสำหรับฉัน


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

@roaima ใช้งานได้เฉพาะเมื่อbackupcopyปิดตัวเลือก
Gilles 'SO- หยุดความชั่วร้าย'

คำตอบ:


15

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

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

ในทางกลับกันใช้กลยุทธ์การเขียนแล้วย้าย - บางสิ่งบางอย่างเพื่อผลของ

echo 'new content' >somefile.new
mv -f somefile.new somefile

เกิดอะไรขึ้นกับเวอร์ชันเก่าของไฟล์คือมันจะถูกลบไป ณ จุดที่ย้ายเวอร์ชั่นใหม่เข้าที่ ณ จุดนี้inotifywaitคำสั่งจะส่งคืนเนื่องจากไฟล์ที่ถูกบอกให้ดูไม่มีอยู่อีกต่อไป ( somefileไฟล์ใหม่เป็นไฟล์อื่นที่มีชื่อเหมือนกัน) หาก Vim ได้รับการกำหนดค่าให้สร้างไฟล์สำรองข้อมูลสิ่งที่จะเกิดขึ้นคือ

echo 'new content' >somefile.new
ln somefile somefile.old
mv -f somefile.new somefile

และinotifywaitตอนนี้จะดูการสำรองข้อมูล

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

สามารถบอกเป็นกลุ่มเพื่อใช้กลยุทธ์การเขียนทับ: ปิดbackupcopyตัวเลือก ( :set nobackupcopy) นี่คือความเสี่ยงตามที่ระบุไว้ข้างต้น

ในการจัดการทั้งประหยัดกลยุทธ์ดูไดเรกทอรีและกรองทั้งสองclose_writeและกิจกรรมสำหรับmoved_tosomefile

inotifywait -m -e close_write,moved_to --format %e/%f . |
while IFS=/ read -r events file; do
  if [ "$file" = "somefile" ]; then
    …
  fi
done

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

@LimitedAtonement นั่นเป็นกรณีการใช้งานที่ยุ่งยากมากกว่าในคำถามนี้ สำหรับกรณีการใช้งานของคุณคุณจะต้องรอสักครู่หลังจากบันทึกไฟล์หนึ่งไฟล์ ไฟล์จะไม่ถูกแก้ไข“ พร้อมกัน” จริงๆ หากคุณบันทึกหลายไฟล์ด้วย:waคุณจะได้รับการแจ้งเหตุการณ์ต่อเนื่อง คุณต้องรอหลังจากคนแรกเพื่อดูว่าคนอื่นจะมา แต่คุณสามารถใช้รหัสที่นำเสนอนี้: ความซับซ้อนเพิ่มเติมจะไปภายใน
Gilles 'หยุดความชั่วร้าย'

@Gilles ฉันตัดสินใจwhile true; do inotifywait ... [no -m]; make; sleep .1; done;หรือมากกว่านั้น มี gotchas อยู่บ้าง แต่ฉันได้มาถึงสิ่งที่สามารถใช้การได้
การชดเชยที่ จำกัด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.