簡體   English   中英

同步shell腳本執行

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM