AGGIORNAMENTO: Sebbene non risolvendo effettivamente il problema originale presentato per quanto riguarda i miei sforzi di piping, ho risolto il mio problema semplificandolo notevolmente e abbandonando del tutto i tubi. Ecco uno script proof-of-concept che genera, parallelamente durante la lettura di una sola volta dal disco, i checksum CRC32, MD5, SHA1, SHA224, SHA256, SHA384 e SHA512 e li restituisce come oggetto JSON (utilizzerà l'output in PHP e Ruby). E 'grezzo, senza controllo degli errori, ma funziona:Possibile condizione di competizione con uscita in pipe da più destinatari di t in arrivo fuori sequenza su una pipe denominata in uno script BASH
#!/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}}"
la domanda iniziale:
Sono un po' paura di fare questa domanda, come ho avuto tante visite per la mia frase di ricerca che dopo l'applicazione del conoscenza raccolta da Using named pipes with bash - Problem with data loss, e la lettura attraverso altre 20 pagine, sono ancora un po 'ferma con questo.
Quindi, per continuare comunque, sto facendo un semplice script per consentirmi di creare contemporaneamente checksum CRC32, MD5 e SHA1 su un file mentre lo leggo solo da disco una sola volta. Sto usando cfv per quello scopo.
Originariamente, ho appena hackerato un semplice script che ha scritto cat'ted il file in tee con tre comandi cfv che scrivevano su tre file separati in/tmp /, e poi ho provato a inviarli allo stdout in seguito, ma alla fine con output vuoto a meno che non abbia fatto dormire il mio script per un secondo prima di provare a leggere i file. Pensando che fosse strano, immaginavo di essere un idiota nel mio scripting, quindi ho provato a fare un approccio diverso facendo in modo che i worker di cfv producessero in una named pipe. Finora, questo è il mio script, dopo aver tecniche applicate da collegamento suindicato:
!/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
Così, eseguito così com'è, ottengo questo output:
[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
Ma, con i 1s sonno commentate , ho l'uscita ottenere previsto,
[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
Questo mi lascia perplesso, come mi piacerebbe pensare che tee non sarebbe uscita fino a dopo ogni destinatario CFV si biforca dati è uscito, e quindi l'eco "EOP" affermazione sarebbe ex ecute fino a quando tutti i substream di cfv non sono terminati, il che significherebbe che avrebbero scritto il loro output sulla mia named pipe ... E quindi l'istruzione echo sarebbe stata eseguita.
Dato che il comportamento è lo stesso senza pipe, utilizzando solo i file temporanei di output, penso che questo debba essere una condizione di competizione che riguarda il modo in cui tee spinge i dati sui suoi destinatari? Ho provato un semplice comando "wait", ma ovviamente aspetterò che il mio processo bash child - the while loop - finisca, quindi ho appena un processo di sospensione.
Qualche idea?
TIA, Daniel :)
Mi aspetto che ci sia il codice sorgente disponibile per questi checksum. Che ne dici di combinarli in 1 programma e di scrivere 3 valori da elaborare nel file di checksum appropriato. Devo credere che perl probabilmente ci sono dei moduli per questo, che, ancora una volta, potresti farti unire insieme per fare solo 1 passaggio sul file. (Sto solo pensando al lato della scatola su questo, YRMV). In bocca al lupo! – shellter
Questo aiuto? 'parallel --group 'cfv -C -t sfv -f {} -; cfv -C -t sha1 -f {} -; cfv -C -t md5 -f {} -;' ::: file' – potong
@shelter - Credo che scrivere le mie routine sia sempre la mia riserva, ma preferirei usare gli strumenti già disponibili per quanto possibile. – DanielSmedegaardBuus