同步shell脚本执行
-
16-09-2019 - |
题
一个壳脚本从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;
然而,这仍然留下了竞争条件。
解决方案
在“锁文件”命令提供你想要的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
另外,你可以把锁文件不断重试下去,所以你不需要测试返回码,而是可以测试输出文件以确定是否运行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
有关完整性,也许还找flock
如果你是一组平台,在那里被可靠地提供,需要一个高性能的替代lockfile
。
您可以实现的,它的工作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文件的存在,并且任选地确保锁文件的日期不是太旧(在情况下的处理管芯)之前。如果它不存在,则创建的编码开始之前,将其取出的编码完成后。
您也可以蜂拥而至的文件,但这个只有真正的作品在C你在哪里调用flock()和写入文件,然后关闭和解锁。对于一个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 -- flac ....