ОБНОВЛЕНИЕ: Хотя на самом деле я не решал исходную проблему, связанную с моими усилиями в области трубопроводов, я решил свою проблему, значительно упростив ее и просто отказавшись от труб. Вот сценарий проверки концепции, который параллельно генерирует при чтении только один раз с диска контрольные суммы 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 для этой цели.
Первоначально, я просто взломал простой скрипт, который написал cat'ted файл для тройки с тремя командами cfv, записывающими в три отдельных файла в / tmp /, а затем попытался отследить их в stdout, но потом закончил с пустой вывод, если я не заставил свой сценарий поспать секунду, прежде чем пытаться прочитать файлы. Думая, что это странно, я предположил, что я был дебилом в своих сценариях, поэтому я попытался использовать другой подход, вместо этого выводя работников 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, что будет они бы записали свой вывод в мой именованный канал ... И тогда выполнил бы оператор echo.
Поскольку поведение без конвейеров такое же, только с использованием временных выходных файлов, я думаю, что это должно быть какое-то условие гонки, связанное с тем, как тройник передает данные своим получателям? Я попробовал простую команду «подождать», но она, конечно, будет ждать завершения моего дочернего процесса bash - цикла while - поэтому я просто получаю зависание процесса.
Есть идеи?
ТИА,
Даниил:)