[英]Synchronize shell script execution
shell腳本的修改版本將音頻文件從FLAC轉換為MP3格式。 該計算機具有四核CPU。 該腳本使用以下命令運行:
./flac2mp3.sh $(find flac -type f)
這會將flac
目錄中的FLAC文件(文件名中沒有空格)轉換為mp3
目錄中的mp3
文件(與flac
處於同一級別)。 如果目標MP3文件已存在,則腳本將跳過該文件。
問題是,有時兩個腳本實例幾乎同時檢查是否存在相同的MP3文件,導致MP3文件損壞。
如何多次運行腳本(即每個核心一次),而不必在每個命令行上指定不同的文件集,而不覆蓋工作?
更新 - 最小競爭條件
該腳本使用以下鎖定機制:
# Convert FLAC to MP3 using tags from flac file.
#
if [ ! -e $FLAC.lock ]; then
touch $FLAC.lock
flac -dc "$FLAC" | lame${lame_opts} \
--tt "$TITLE" \
--tn "$TRACKNUMBER" \
--tg "$GENRE" \
--ty "$DATE" \
--ta "$ARTIST" \
--tl "$ALBUM" \
--add-id3v2 \
- "$MP3"
rm $FLAC.lock
fi;
然而,這仍然留下了競爭條件。
“lockfile”命令提供了在沒有競爭條件的情況下嘗試為shell腳本執行的操作。 該命令由procmail人員專門為此目的編寫,並且可在大多數BSD / Linux系統上使用(因為procmail適用於大多數環境)。
你的測試變成這樣:
lockfile -r 3 $FLAC.lock
if test $? -eq 0 ; then
flac -dc "$FLAC" | lame${lame_opts} \
--tt "$TITLE" \
--tn "$TRACKNUMBER" \
--tg "$GENRE" \
--ty "$DATE" \
--ta "$ARTIST" \
--tl "$ALBUM" \
--add-id3v2 \
- "$MP3"
fi
rm -f $FLAC.lock
或者,您可以使lockfile保持無限期重試,這樣您就不需要測試返回代碼,而是可以測試輸出文件以確定是否運行flac。
如果您沒有lockfile
並且無法安裝它(在任何版本中 - 有幾個實現),強大且可移植的原子互斥鎖是mkdir
。
如果您嘗試創建的目錄已存在,則mkdir
將失敗,因此您可以檢查該目錄; 當創建成功時,您可以保證在代碼的同時,關鍵部分中沒有其他協作進程。
if mkdir "$FLAC.lockdir"; then
# you now have the exclusive lock
: critical section
: code goes here
rmdir "$FLAC.lockdir"
else
: nothing? to skip this file
# or maybe sleep 1 and loop back and try again
fi
為了完整性,如果您在一組可靠地提供並且需要lockfile
替代平台的平台上,也可以尋找flock
。
您可以實現鎖定正在處理的FLAC文件。 就像是:
if (not flac locked)
lock flac
do work
else
continue to next flac
將輸出發送到具有唯一名稱的臨時文件,然后將文件重命名為所需名稱。
flac -dc "$FLAC" | lame${lame_opts} \
--tt "$TITLE" \
--tn "$TRACKNUMBER" \
--tg "$GENRE" \
--ty "$DATE" \
--ta "$ARTIST" \
--tl "$ALBUM" \
--add-id3v2 \
- "$MP3.$$"
mv "$MP3.$$" "$MP3"
如果競爭條件每隔一段時間通過文件鎖定系統泄漏,最終輸出仍將是一個進程的結果。
要鎖定文件進程,您可以創建具有相同名稱且擴展名為.lock的文件。
在開始編碼之前檢查.lock文件是否存在,並且可選地確保lockfile的日期不是太舊(以防進程死亡)。 如果它不存在,請在編碼開始之前創建它,並在編碼完成后將其刪除。
你也可以flock文件,但這只適用於你調用flock()並寫入文件然后關閉和解鎖的c。 對於shell腳本,您可能正在調用另一個實用程序來編寫該文件。
如何編寫Makefile?
ALL_FLAC=$(wildcard *.flac)
ALL_MP3=$(patsubst %.flac, %.mp3, $(ALL_FLAC)
all: $(ALL_MP3)
%.mp3: %.flac
$(FLAC) ...
然后做
$ make -j4 all
在bash中,可以設置noclobber選項以避免文件覆蓋。
幫助集| egrep'noclobber | -C'
使用像FLOM(Free LOck Manager)這樣的工具,只需序列化您的命令,如下所示:
flom -- flac ....
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.