一个的修改版本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;
然而,这仍然留下了竞争条件。
该“锁定文件”命令提供你想要的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
,不能安装它(在任何版本的-有几个实现)一个强大的和便携式原子互斥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 ....