同步shell脚本执行

Dav*_*vis 3 linux bash shell multiprocessing race-condition

shell脚本的修改版本将音频文件从FLAC转换为MP3格式.该计算机具有四核CPU.该脚本使用以下命令运行:

./flac2mp3.sh $(find flac -type f)
Run Code Online (Sandbox Code Playgroud)

这会将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;
Run Code Online (Sandbox Code Playgroud)

然而,这仍然留下了竞争条件.

brl*_*cad 6

"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
Run Code Online (Sandbox Code Playgroud)

或者,您可以使lockfile保持无限期重试,这样您就不需要测试返回代码,而是可以测试输出文件以确定是否运行flac.

  • rm -f $FLAC.lock 应该位于 if 语句内。否则,您可以删除其他进程创建的锁定文件。 (2认同)