Shell 腳本中需要**多進程協同、互斥執行、異步等待完成**時,flock(1) 是比臨時文件、目錄鎖更標準、更可靠的工具。本文通過「並發更新多台服務器套件、等待全部完成再執行後續任務」的實戰場景,詳細講解 flock 的三種調用形式、共享/獨佔鎖語義、非阻塞/超時參數、文件描述符綁定模式,並給出可直接複製的生產級模板。
# 串行執行:慢
update_pkg_on_machine_1
update_pkg_on_machine_2
update_pkg_on_machine_3
# 後台 & + sleep:不可靠
update_pkg_on_machine_1 &
update_pkg_on_machine_2 &
update_pkg_on_machine_3 &
sleep 10 # 10 秒夠嗎?夠不夠都不好
flock [選項] 鎖文件 -c "命令"
flock [選項] 鎖文件 命令 [參數...]
(
flock -s 200
# ... 並發安全代碼 ...
) 200>/var/lock/mylockfile
exec 200>/var/lock/mylockfile
flock -x 200
# ... 臨界區 ...
flock -u 200
exec 200>&-
| 參數 | 說明 |
|---|---|
-s, --shared | 獲取共享鎖 |
-x, -e, --exclusive | 獲取獨佔鎖(默認) |
-n, --nonblock | 無法獲取鎖立即返回 1,不等待 |
-w, --timeout SEC | 等待超時秒數,超時返回 1 |
-o, --close | 執行命令前關閉鎖文件描述符(防止子進程繼承鎖) |
-u, --unlock | 顯式釋放鎖(通常不需要,自動釋放) |
#!/bin/bash
LOCK="/tmp/parallel_tasks.lock"
# 並發啟動三個任務,持有共享鎖
flock -s "$LOCK" ssh host1 "yum update -y" &
flock -s "$LOCK" ssh host2 "yum update -y" &
flock -s "$LOCK" ssh host3 "yum update -y" &
# 等待所有任務完成:獲取獨佔鎖(會阻塞直到所有共享鎖釋放)
flock -x "$LOCK" echo "All tasks completed!"
# 後續串行工作
echo "Proceeding to next stage..."
原理:三個後台任務各持有一把共享鎖,主進程嘗試獲取獨佔鎖 → 因共享/獨佔互斥 → 阻塞等待 → 三個任務結束釋放共享鎖 → 主進程獲得獨佔鎖繼續執行。
# 嘗試獲取鎖,最多等 30 秒
if flock -w 30 -x "$LOCK"; then
critical_section
else
echo "Lock timeout, aborting" >&2
exit 1
fi
# 非阻塞嘗試,獲取失敗直接退出
flock -n -x "$LOCK" || { echo "Another instance running"; exit 1; }
#!/bin/bash
LOCKFILE="/var/run/my_daemon.lock"
exec 200>"$LOCKFILE"
flock -n -x 200 || { echo "Already running" >&2; exit 1; }
# 守護邏輯
while true; do
do_work
sleep 60
done
flock 是 **Shell 級互斥鎖標準實現**,基於 `flock(2)` 系統調用,跨 Shell、跨進程有效。flock 納入腳本工具箱,徹底告別 sleep 猜謎與臨時文件競態。Linux 實戰:使用 extundelete 秒級恢復誤刪除的關鍵檔案
Linux 下使用 OpenSSL 生成 SSL 證書完整教學
Linux 硬盤壞道檢測與修復全指南:badblocks、fsck、磁盤原理、分區屏蔽策略
Linux 安裝 ImageMagick 與 JMagick 完整教學:RPM 與原始碼編譯雙軌並行
awk 經典慣用語解析:`awk '{$2=$5=\"\"}1' file` 到底在做什麼?
Linux 與 Windows 檔案互傳實戰:FTP 伺服器 架設與指令操作全指南
Git 推送錯誤 "git did not exit cleanly (exit code 128)" 解決:Bitbucket 團隊成員超過 5 人限制