ОБНОВЛЕНИЕ: Хотя на самом деле я не решил первоначальную проблему, связанную с моими усилиями по прокладке труб, я решил свою проблему, значительно упростив ее и просто полностью отказавшись от труб. Вот сценарий проверки концепции, который генерирует параллельно при чтении только один раз с диска контрольные суммы CRC32, MD5, SHA1, SHA224, SHA256, SHA384 и SHA512 и возвращает их как объект JSON (будет использовать вывод в PHP и Руби). Это грубо без проверки ошибок, но работает:
#!/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}}"
ИСХОДНЫЙ ВОПРОС:
Я немного боюсь задавать этот вопрос, так как я получил так много попаданий по моей поисковой фразе, что после применения знаний, полученных из Использование именованных каналов с bash - проблема с потерей данных, и прочитав еще 20 страниц, я все еще немного застопорился с этим.
Итак, чтобы продолжить, тем не менее, я делаю простой сценарий, позволяющий мне одновременно создавать контрольные суммы CRC32, MD5 и SHA1 для файла, считывая его с диска только один раз. Я использую cfv для этой цели.
Первоначально я просто взломал простой скрипт, который записал файл в тройник с тремя командами cfv, записывающими в три отдельных файла в каталоге /tmp/, а затем попытался вывести их на стандартный вывод после этого, но в итоге получил пустой вывод, если только Я заставил свой скрипт спать на секунду, прежде чем пытаться прочитать файлы. Думая, что это странно, я предположил, что был идиотом в своих сценариях, поэтому я попытался использовать другой подход, заставив вместо этого рабочие процессы cfv выводить данные в именованный канал. Пока что это мой сценарий после применения методов из вышеупомянутой ссылки:
!/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
Итак, выполненный в том виде, в котором он есть, я получаю этот вывод:
daniel@lnxsrv:~/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)
daniel@lnxsrv:~/tisso$ close failed in file object destructor:
sys.excepthook is missing
lost sys.stderr
Но, закомментировав спящие 1, я получаю ожидаемый результат,
daniel@lnxsrv:~/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
Это озадачивает меня, так как я предполагаю, что tee не завершится до тех пор, пока каждый получатель cfv не разветвит данные, и, таким образом, оператор echo "EOP" будет выполняться до тех пор, пока не закончатся все подпотоки cfv, что означало бы, что они записали свой вывод в мой именованный канал... И тогда будет выполнен оператор эха.
Поскольку поведение такое же без каналов, просто с использованием выходных временных файлов, я думаю, что это должно быть какое-то состояние гонки, связанное с тем, как тройник отправляет данные своим получателям? Я попробовал простую команду «ждать», но она, конечно, дождется завершения моего дочернего процесса bash — цикла while, поэтому я просто получаю зависший процесс.
Любые идеи?
ТИА, Дэниел :)
parallel --group 'cfv -C -t sfv -f {} - ;cfv -C -t sha1 -f {} - ;cfv -C -t md5 -f {} - ;' ::: file
- person potong   schedule 10.03.2012