ฉันต้องการเรียกใช้สคริปต์เชลล์ Bash หลายชุดพร้อมกัน อย่างไรก็ตามฉันต้องการหลีกเลี่ยงสภาพการแข่งขัน คำสั่ง Unix ใดที่เป็นอะตอมมิกอย่างแท้จริงที่ฉันสามารถใช้เพื่อจุดประสงค์นี้และฉันจะใช้ได้อย่างไร
ฉันต้องการเรียกใช้สคริปต์เชลล์ Bash หลายชุดพร้อมกัน อย่างไรก็ตามฉันต้องการหลีกเลี่ยงสภาพการแข่งขัน คำสั่ง Unix ใดที่เป็นอะตอมมิกอย่างแท้จริงที่ฉันสามารถใช้เพื่อจุดประสงค์นี้และฉันจะใช้ได้อย่างไร
คำตอบ:
หากlockfile
ไม่ได้ติดตั้งบนระบบของคุณmkdir
จะทำงาน: เป็นการดำเนินการแบบปรมาณูและจะล้มเหลวหากมีไดเรกทอรีอยู่แล้ว (ตราบใดที่คุณไม่เพิ่ม-p
สวิตช์บรรทัดคำสั่ง)
create_lock_or_wait () {
path="$1"
wait_time="${2:-10}"
while true; do
if mkdir "${path}.lock.d"; then
break;
fi
sleep $wait_time
done
}
remove_lock () {
path="$1"
rmdir "${path}.lock.d"
}
#!/bin/bash
# Makes sure we exit if flock fails.
set -e
(
# Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
flock -x -w 10 200
# Do stuff
) 200>/var/lock/.myscript.exclusivelock
สิ่งนี้ทำให้มั่นใจได้ว่ารหัสระหว่าง "(" และ ")" จะถูกเรียกใช้โดยกระบวนการเดียวเท่านั้นในแต่ละครั้งและกระบวนการนั้นจะรอการล็อคนานเกินไป
lockf(1)
มีคำสั่งที่คล้ายกัน:
lockf(1)
แม้ว่าจะไม่ทำงานในวิธีที่ใช้ในตัวอย่างนี้ ไม่สามารถใช้หมายเลขตัวอธิบายไฟล์เป็นอาร์กิวเมนต์ได้
lockfile (1) ดูเหมือนว่าจะเป็นตัวเลือกที่ดี แต่ระวังว่ามันเป็นส่วนหนึ่งของแพ็คเกจprocmailซึ่งคุณอาจยังไม่ได้ติดตั้งในเครื่องของคุณ มันเป็นแพคเกจที่ได้รับความนิยมมากพอที่จะบรรจุในระบบของคุณหากยังไม่ได้ติดตั้ง สามในสี่ระบบที่ฉันตรวจสอบมีอยู่และอีกอันใช้งานได้
ใช้ง่ายมาก:
#!/bin/sh
LOCKFILE=$HOME/.myscript/lock
mkdir -p `dirname $LOCKFILE`
echo Waiting for lock $LOCKFILE...
if lockfile -1 -r15 $LOCKFILE
then
# Do protected stuff here
echo Doing protected stuff...
# Then, afterward, clean up so another instance of this script can run
rm -f $LOCKFILE
else
echo "Failed to acquire lock! lockfile(1) returned $?"
exit 1
fi
ตัวเลือกที่ฉันให้ลองใหม่อีกครั้งหนึ่งครั้งนานถึง 15 วินาที ปล่อยแฟล็ก "-r" หากคุณต้องการรอตลอดไป
การเรียกระบบmkdir()
เป็น atomic บนระบบไฟล์ POSIX ดังนั้นการใช้mkdir
คำสั่งในลักษณะที่เกี่ยวข้องกับการเรียกเพียงครั้งเดียวเพื่อmkdir()
ให้บรรลุวัตถุประสงค์ของคุณ (IOW อย่าใช้mkdir -p
) rmdir
แน่นอนว่าการปลดล็อกที่เกี่ยวข้องนั้น
Caveat emptor: mkdir()
อาจไม่เป็น atomic บนระบบไฟล์เครือข่าย
rmdir
ดังนั้นจึงเป็นอะตอม
บางทีคำสั่ง lockfile จะทำสิ่งที่คุณต้องการ
lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock
หากคุณใช้ระบบปฏิบัติการยูนิกซ์เท่านั้นให้ใช้ fifos คุณสามารถเขียนบันทึกการทำงานไปยัง Fifo และมีกระบวนการอ่านจากไฟล์นี้และผู้อ่านของคุณจะบล็อกใน Fifos
ไฟล์ล็อคก็โอเค แต่สำหรับสิ่งที่คุณอธิบายฉันจะไปกับ Fifos
ตามที่โพสต์ที่นี่: " แก้ไขการล็อคในเชลล์สคริปต์ได้หรือไม่ " โดยใช้เครื่องมือFLOM (Free Lock Manager)คำสั่งการทำให้เป็นอันดับและสคริปต์เชลล์จะกลายเป็นเรื่องง่ายเหมือนการทำงาน
flom -- command_to_serialize
FLOM ช่วยให้คุณสามารถใช้กรณีการใช้งานที่ซับซ้อนมากขึ้น (การล็อกแบบกระจายผู้อ่าน / ผู้เขียนทรัพยากรตัวเลข ฯลฯ ... ) ตามที่อธิบายไว้ที่นี่: http://sourceforge.net/p/flom/wiki/FLOM%20by%20examples/
make(1)
จะใช้เวลามากกว่า? (เช่นทำmake -j 9
ถ้าคุณมี 8 แกน) นี่เป็นข้อได้เปรียบที่เพิ่มเข้ามาของการทำงานแบบแทรกสอดด้วยความละเอียดปลีกย่อย