หาก Apache กำลังเขียนไฟล์บางชนิดไปยังที่เดียวและยังเขียนไม่เสร็จและ rsync
เริ่มเล่นใหม่rsync
จะคัดลอกไฟล์ที่อยู่ในนั้น
หมายความว่าหาก Apache กำลังจัดการกับไฟล์ 5MB จะมีเพียง 2MB เท่านั้นที่เขียนและrsync
เริ่มทำงานไฟล์ 2MB บางส่วนจะถูกคัดลอก ดังนั้นไฟล์นั้นจะดูเหมือนว่า“ เสียหาย” บนเซิร์ฟเวอร์ปลายทาง
ขึ้นอยู่กับขนาดของไฟล์ที่คุณใช้คุณสามารถใช้--inplace
ตัวเลือกในrsync
การทำสิ่งต่อไปนี้:
ตัวเลือกนี้จะเปลี่ยนวิธีการถ่ายโอนไฟล์ rsync เมื่อข้อมูลของไฟล์จำเป็นต้องได้รับการอัปเดต: แทนที่จะเป็นวิธีการเริ่มต้นในการสร้างสำเนาใหม่ของไฟล์และย้ายไปยังตำแหน่งเมื่อเสร็จสมบูรณ์ rsync จะเขียนข้อมูลที่อัพเดทโดยตรงไปยังปลายทางแทน ไฟล์.
ประโยชน์ของการทำเช่นนี้คือหากไฟล์ 5MB มีการคัดลอกเพียง 2MB ในการเรียกใช้ครั้งแรกการเรียกใช้ครั้งต่อไปจะรับที่ 2MB และทำการคัดลอกไฟล์ต่อไปจนกว่าจะมีการใช้งาน 5MB แบบเต็ม
ข้อเสียคือสามารถสร้างสถานการณ์ที่มีคนกำลังเข้าถึงเว็บเซิร์ฟเวอร์ในขณะที่กำลังคัดลอกไฟล์จากนั้นพวกเขาจะเห็นไฟล์บางส่วน ในความคิดของฉันrsync
ทำงานได้ดีที่สุดเพราะเป็นพฤติกรรมเริ่มต้นของการแคชไฟล์ "ที่มองไม่เห็น" จากนั้นย้ายไปไว้ที่เดิม แต่--inplace
จะดีสำหรับสถานการณ์ที่ไฟล์ขนาดใหญ่และข้อ จำกัด แบนด์วิดท์อาจยืนในทางของไฟล์ขนาดใหญ่ที่ถูกคัดลอกได้อย่างง่ายดายจากตารางที่หนึ่ง
ที่กล่าวว่าคุณทำรัฐนี้ เน้นเป็นของฉัน:
ทุกๆห้านาทีมี cron run rsync ...
ดังนั้นฉันคิดว่าคุณมีสคริปต์ทุบตีเพื่อจัดการงาน cron นี้หรือไม่ สิ่งนี้rsync
ฉลาดพอที่จะคัดลอกเฉพาะไฟล์ที่จำเป็นต้องคัดลอกเท่านั้น และถ้าคุณมีสคริปต์ที่ทำงานทุก 5 นาทีดูเหมือนว่าคุณกำลังพยายามหลีกเลี่ยงrsync
ขั้นตอนซึ่งกันและกันหากสคริปต์ทำงานได้เร็วขึ้น หมายความว่าหากคุณใช้งานทุกนาทีมีความเสี่ยงที่กระบวนการอย่างน้อยหนึ่งrsync
กระบวนการยังคงทำงานเนื่องจากขนาดไฟล์หรือความเร็วเครือข่ายและกระบวนการถัดไปจะเป็นการแข่งขันกับมัน สภาพการแข่งรถ
วิธีหนึ่งในการหลีกเลี่ยงปัญหานี้คือการห่อrsync
คำสั่งทั้งหมดของคุณในสคริปต์ทุบตีที่ตรวจสอบการล็อกไฟล์ ด้านล่างเป็นกรอบสคริปต์ทุบตีสำเร็จรูปที่ฉันใช้สำหรับกรณีเช่นนี้
โปรดทราบว่าบางคนจะแนะนำให้ใช้flock
แต่เนื่องจากflock
ไม่ได้ติดตั้งในบางระบบที่ฉันใช้ - และฉันกระโดดระหว่าง Ubuntu (ซึ่งมี) และ Mac OS X (ซึ่งไม่ได้) มากฉันใช้กรอบง่าย ๆ นี้โดยไม่มีปัญหาจริง:
LOCK_NAME="MY_GREAT_BASH_SCRIPT"
LOCK_DIR='/tmp/'${LOCK_NAME}.lock
PID_FILE=${LOCK_DIR}'/'${LOCK_NAME}'.pid'
if mkdir ${LOCK_DIR} 2>/dev/null; then
# If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE}
echo $$ > ${PID_FILE}
echo "Hello world!"
rm -rf ${LOCK_DIR}
exit
else
if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then
# Confirm that the process file exists & a process
# with that PID is truly running.
echo "Running [PID "$(cat ${PID_FILE})"]" >&2
exit
else
# If the process is not running, yet there is a PID file--like in the case
# of a crash or sudden reboot--then get rid of the ${LOCK_DIR}
rm -rf ${LOCK_DIR}
exit
fi
fi
ความคิดคือแกนกลางทั่วไป - ที่ฉันมีecho "Hello world!"
- เป็นหัวใจของสคริปต์ของคุณ ส่วนที่เหลือของมันนั้นเป็นกลไกการล็อค / mkdir
ตรรกะขึ้นอยู่กับ คำอธิบายที่ดีของแนวคิดอยู่ในคำตอบนี้ :
mkdirสร้างไดเรกทอรีถ้ามันยังไม่มีอยู่และถ้ามันทำมันจะตั้งรหัสทางออก ที่สำคัญมันทำสิ่งนี้ทั้งหมดในการกระทำปรมาณูเดียวทำให้มันสมบูรณ์แบบสำหรับสถานการณ์นี้
ดังนั้นในกรณีของคุณrsync
ขั้นตอนที่ผมจะแนะนำให้ใช้สคริปต์นี้โดยเพียงแค่การเปลี่ยนecho
คำสั่งที่คุณrsync
สั่ง นอกจากนี้เปลี่ยนLOCK_NAME
สิ่งที่ชอบRSYNC_PROCESS
แล้วคุณก็ไปดี
ขณะนี้ด้วยrsync
สคริปต์ของคุณในตอนนี้คุณสามารถตั้งค่า cron job ให้ทำงานทุก ๆ นาทีโดยไม่ต้องเสี่ยงกับสภาพการแข่งขันที่rsync
กระบวนการสองอย่างหรือมากกว่านั้นกำลังต่อสู้เพื่อทำสิ่งเดียวกัน วิธีนี้จะช่วยให้คุณเพิ่มความเร็วหรือrsync
อัปเดตซึ่งจะไม่ขจัดปัญหาของไฟล์บางส่วนที่ถูกถ่ายโอน แต่มันจะช่วยเร่งความเร็วกระบวนการโดยรวมเพื่อให้สามารถคัดลอกไฟล์เต็มรูปแบบได้อย่างถูกต้องในบางจุด