Shell腳本進(jìn)程鎖機(jī)制解析
這段 Shell 腳本主要實現(xiàn)了進(jìn)程鎖機(jī)制,用于確保同一時間只有一個實例在運行。讓我逐行解讀:
代碼功能分析
1. 命令行參數(shù)解析 (第9-21行)
while getopts "m:o:r:" arg; do
case $arg in
# ... 參數(shù)處理邏輯(代碼中省略了具體內(nèi)容)
esac
done
- 使用
getopts解析命令行參數(shù) - 支持三個帶參數(shù)的選項:
-m、-o、-r - 具體處理邏輯在代碼中被省略了
2. 文件鎖機(jī)制 (第23-34行)
這是代碼的核心部分:
LOCK_FILE="/tmp/gen_emmc_img.lock" echo "Waiting for lock for model gen_emmc_img..." exec 200>"$LOCK_FILE" # 將文件描述符200重定向到鎖文件 flock 200 # 對文件描述符200加鎖 echo "Lock acquired for gen_emmc_img!"
鎖機(jī)制的工作原理:
- 創(chuàng)建鎖文件
/tmp/gen_emmc_img.lock - 使用
flock命令對文件描述符200加鎖 - 如果鎖已被占用,腳本會阻塞等待直到鎖可用
3. 清理和鎖釋放 (第30-34行)
_cleanup_flock() {
echo "Releasing lock for gen_emmc_img!"
flock -u 200 # 釋放文件描述符200的鎖
}
trap _cleanup_flock EXIT # 設(shè)置陷阱,在腳本退出時自動調(diào)用清理函數(shù)
設(shè)計目的
這種設(shè)計主要用于:
- 防止并發(fā)沖突:確保同一時間只有一個
gen_emmc_img.sh進(jìn)程在運行 - 資源保護(hù):在生成 eMMC 鏡像時避免多個進(jìn)程同時操作導(dǎo)致的沖突
- 自動清理:使用
trap確保即使腳本異常退出也能釋放鎖
典型應(yīng)用場景
在嵌入式開發(fā)或系統(tǒng)鏡像生成過程中,這種鎖機(jī)制很常見,用于保護(hù):
- 對存儲設(shè)備的獨占訪問
- 臨時文件的創(chuàng)建和使用
- 系統(tǒng)關(guān)鍵資源的訪問
這是一個很經(jīng)典的 Shell 腳本并發(fā)控制實現(xiàn)!
好的,我來深度解讀第23-34行的文件鎖機(jī)制。這部分代碼確實比較巧妙,讓我詳細(xì)分解:
逐行深度解析
第23行:定義鎖文件路徑
LOCK_FILE="/tmp/gen_emmc_img.lock"
- 在系統(tǒng)的臨時目錄創(chuàng)建一個鎖文件
- 文件名包含腳本名稱,避免與其他腳本沖突
第26行:文件描述符重定向
exec 200>"$LOCK_FILE"
這是關(guān)鍵的一步:
exec命令在當(dāng)前shell進(jìn)程中執(zhí)行重定向200>表示將文件描述符200重定向到鎖文件- 如果文件不存在會自動創(chuàng)建,存在則截斷
- 文件描述符200是一個任意選擇的大于2的數(shù)字(避免與stdin=0, stdout=1, stderr=2沖突)
第27行:獲取文件鎖
flock 200
flock 命令的工作原理:
- 對文件描述符200指向的文件加鎖
- 這是** advisory lock**(建議性鎖),不是強制性鎖
- 如果鎖已被其他進(jìn)程持有,當(dāng)前進(jìn)程會阻塞等待
- 鎖的釋放發(fā)生在文件描述符關(guān)閉時
第30-33行:清理函數(shù)
_cleanup_flock() {
echo "Releasing lock for gen_emmc_img!"
flock -u 200 # 顯式釋放鎖
}
第34行:陷阱設(shè)置
trap _cleanup_flock EXIT
trap 的作用:
- 注冊一個信號處理程序
EXIT是一個偽信號,在shell退出時觸發(fā)- 無論腳本正常結(jié)束還是異常退出,都會調(diào)用
_cleanup_flock
鎖機(jī)制的工作原理示意圖
進(jìn)程A啟動
↓
exec 200>lockfile # 創(chuàng)建文件描述符
↓
flock 200 # 加鎖成功,繼續(xù)執(zhí)行
↓
[執(zhí)行關(guān)鍵代碼...]
↓
腳本結(jié)束 → trap觸發(fā) → flock -u 200 → 釋放鎖
進(jìn)程B啟動(當(dāng)A持有鎖時)
↓
exec 200>lockfile # 創(chuàng)建文件描述符
↓
flock 200 # 阻塞等待...
↓ # 當(dāng)進(jìn)程A釋放鎖后
flock返回 → 獲得鎖,繼續(xù)執(zhí)行
為什么需要這樣設(shè)計?
1.原子性操作
# 如果沒有flock,你可能會這樣寫(有競態(tài)條件):
if [ ! -f "$LOCK_FILE" ]; then
touch "$LOCK_FILE" # 這里可能有多個進(jìn)程同時通過檢查
# 執(zhí)行任務(wù)...
rm "$LOCK_FILE"
fi
2.自動清理保障
即使腳本被 Ctrl+C 中斷、發(fā)生錯誤退出,trap EXIT 也能確保鎖被釋放。
3.避免僵尸鎖
傳統(tǒng)方法可能因為進(jìn)程崩潰而留下鎖文件,導(dǎo)致系統(tǒng)永久鎖定。這里使用內(nèi)核管理的文件鎖,進(jìn)程退出后鎖自動釋放。
實際執(zhí)行流程示例
# 終端1:運行腳本 $ ./gen_emmc_img.sh Waiting for lock for model gen_emmc_img... Lock acquired for gen_emmc_img! [正在執(zhí)行...] # 終端2:同時運行另一個實例 $ ./gen_emmc_img.sh Waiting for lock for model gen_emmc_img... # 這里會阻塞等待,直到終端1的腳本結(jié)束 # 當(dāng)終端1腳本結(jié)束時: Releasing lock for gen_emmc_img! # 終端2立即獲得鎖并繼續(xù)執(zhí)行
文件鎖的優(yōu)勢
- 跨進(jìn)程同步:不同shell實例之間可以同步
- 自動清理:進(jìn)程退出時鎖自動釋放
- 內(nèi)核級別:比基于文件的標(biāo)記更可靠
- 可移植性:大多數(shù)Unix-like系統(tǒng)都支持
這種設(shè)計在需要保證單實例運行的腳本中非常常見,特別是在處理硬件操作(如eMMC燒錄)時尤為重要。
到此這篇關(guān)于Shell腳本進(jìn)程鎖機(jī)制解析的文章就介紹到這了,更多相關(guān)Shell 進(jìn)程鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
putty實現(xiàn)自動登錄的方法(ssh和ssh2)
這篇文章主要介紹putty實現(xiàn)自動登錄的方法,需要的朋友可以參考下2013-02-02
利用expect命令實現(xiàn)Shell自動化交互的方法詳解
我們通過Shell可以實現(xiàn)簡單的控制流功能,如:循環(huán)、判斷等。下面這篇文章主要給大家介紹了關(guān)于利用expect命令實現(xiàn)Shell自動化交互的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-12-12
使用shell檢查并修復(fù)mysql數(shù)據(jù)庫表的腳本
這篇文章主要介紹了使用shell檢查并修復(fù)mysql數(shù)據(jù)庫表的腳本,需要的朋友可以參考下2014-03-03
Shell中實現(xiàn)整數(shù)自增的幾種方法示例
Linux Shell中寫循環(huán)時,常常要用到變量的自增,下面這篇文章主要給大家分享了關(guān)于Shell中實現(xiàn)整數(shù)變量自增的幾種方法,包括declare -i來聲明、使用let命令、使用(())以及使用expr命令等等方法,需要的朋友可以參考借鑒,下面來一起看看吧。2017-08-08
Linux?for循環(huán)之列表for循環(huán)詳解
文章詳細(xì)介紹了Linux?shell中的for循環(huán)結(jié)構(gòu),重點分析列表for循環(huán)的三種形式:數(shù)字列表、字符串列表、命令列表及腳本傳參列表,通過使用seq命令和跳步方式實現(xiàn)循環(huán)控制,并說明字符串列表的使用方法2025-09-09

