更新:虽然没有真正解决带有问候我管的努力原来的问题,我已经解决了我的问题通过大大简化它,并且完全抛弃管道。这是一个概念证明脚本,它可以并行生成一次,同时从磁盘读取一次CRC32,MD5,SHA1,SHA224,SHA256,SHA384和SHA512校验和,并将它们作为JSON对象返回(将使用PHP中的输出和Ruby)。这是没有错误检查粗糙,但它的工作原理:可能的竞争条件
#!/bin/bash
checksums="`tee <"$1" \
>(cfv -C -q -t sfv -f - - | tail -n 1 | sed -e 's/^.* \([a-fA-F0-9]\{8\}\)$/"crc32":"\1"/') \
>(md5sum - | sed -e 's/^\([a-fA-F0-9]\{32\}\) .*$/"md5":"\1"/') \
>(sha1sum - | sed -e 's/^\([a-fA-F0-9]\{40\}\) .*$/"sha1":"\1"/') \
>(sha224sum - | sed -e 's/^\([a-fA-F0-9]\{56\}\) .*$/"sha224":"\1"/') \
>(sha256sum - | sed -e 's/^\([a-fA-F0-9]\{64\}\) .*$/"sha256":"\1"/') \
>(sha384sum - | sed -e 's/^\([a-fA-F0-9]\{96\}\) .*$/"sha384":"\1"/') \
>(sha512sum - | sed -e 's/^\([a-fA-F0-9]\{128\}\) .*$/"sha512":"\1"/') \
>/dev/null`\
"
json="{"
for checksum in $checksums; do json="$json$checksum,"; done
echo "${json:0: -1}}"
原题:
我有点不敢问这个问题,因为我有这么多的点击了搜索短语,申请后从Using named pipes with bash - Problem with data loss收获的知识,并通过另外20页的阅读,我仍然对此有点停滞不前。
因此,继续尽管如此,我做一个简单的脚本,使我对文件同时创建CRC32,MD5,SHA1和校验,而只有从磁盘读取一次。我为此使用了cfv。最初,我只是一个简单的脚本,写了一个简单的脚本,用三个cfv命令写了三个cfv命令,然后写入/ tmp /下的三个单独的文件,然后尝试将它们提供给标准输出,但最终除非我在尝试读取文件之前让脚本睡了一秒,否则会产生空输出。这种想法很奇怪,我认为我在我的脚本中是一个白痴,所以我试图通过让cfv工作者输出到一个命名管道来做一个不同的方法。到目前为止,这是我的脚本,从forementioned链接具有应用技术后:
!/bin/bash
# Bail out if argument isn't a file:
[ ! -f "$1" ] && echo "'$1' is not a file!" && exit 1
# Choose a name for a pipe to stuff with CFV output:
pipe="/tmp/pipe.chksms"
# Don't leave an orphaned pipe on exiting or being terminated:
trap "rm -f $pipe; exit" EXIT TERM
# Create the pipe (except if it already exists (e.g. SIGKILL'ed b4)):
[ -p "$pipe" ] || mkfifo $pipe
# Start a background process that reads from the pipe and echoes what it
# receives to stdout (notice the pipe is attached last, at done):
while true; do
while read line; do
[ "$line" = "EOP" ] && echo "quitting now" && exit 0
echo "$line"
done
done <$pipe 3>$pipe & # This 3> business is to make sure there's always
# at least one producer attached to the pipe (the
# consumer loop itself) until we're done.
# This sort of works without "hacks", but tail errors out when the pipe is
# killed, naturally, and script seems to "hang" until I press enter after,
# which I believe is actually EOF to tail, so it's no solution anyway:
#tail -f $pipe &
tee <"$1" >(cfv -C -t sfv -f - - >$pipe) >(cfv -C -t sha1 -f - - >$pipe) >(cfv -C -t md5 -f - - >$pipe) >/dev/null
#sleep 1s
echo "EOP" >$pipe
exit
因此,执行的样子,我得到这样的输出:
[email protected]:~/tisso$ ./multisfv file
: : : quitting now
- : Broken pipe (CF)
close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
- : Broken pipe (CF)
close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
- : Broken pipe (CF)
[email protected]:~/tisso$ close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
但是,随着注释掉睡眠1秒我一开始预期的输出,
[email protected]:~/tisso$ ./multisfv file
3bc1b5ff125e03fb35491e7d67014a3e *
-: 1 files, 1 OK. 0.013 seconds, 79311.7K/s
5e3bb0e3ec410a8d8e14fef1a6daababfc48c7ce *
-: 1 files, 1 OK. 0.016 seconds, 62455.0K/s
; Generated by cfv v1.18.3 on 2012-03-09 at 23:45.23
;
2a0feb38
-: 1 files, 1 OK. 0.051 seconds, 20012.9K/s
quitting now
这让我为难,因为我认为发球不会退出,直到之后的每个CFV接收者,它派生的数据已经退出,因此回声“EOP”声明将前直到所有的cfv子流完成,这意味着他们已经将他们的输出写到我命名的管道中了......然后echo语句会执行。
由于行为是没有管相同,只是用输出的临时文件,我想这一定是具有三通将数据推到它的接受者的方式做一些竞争条件?我尝试了一个简单的“等待”命令,但它当然会等待我的bash子进程 - 即while循环 - 完成,所以我只是得到一个挂起的进程。
任何想法?
TIA, 丹尼尔:)一旦写输入的最后一位到最后输出管道,并将其关闭(
我期望有这些校验和的源代码可用。如何将它们组合成1个程序,并将3个值写入相应的校验和文件。我不得不相信,perl可能有这个模块,你可以一起做一个文件传递。 (只是想着这个盒子,YRMV)。祝你好运! – shellter 2012-03-10 01:25:51
这会有帮助吗? 'parallel --group'cfv -C -t sfv -f {} - ; cfv -C -t sha1 -f {} - ; cfv -C -t md5 -f {} - ;' ::: file' – potong 2012-03-10 01:46:36
@shelter - 我想写我自己的例程总是我的后备,但我更愿意使用尽可能多的工具。 – DanielSmedegaardBuus 2012-03-10 08:32:26