Featured post
Bash process substitution and syncing -
(possibly related do programs not accept process substitution input files?)
in bash unit test scripts i'm using following trick log and display stdout , stderr of command:
command > >(tee "${stdoutf}") 2> >(tee "${stderrf}" >&2) this process produces output stdout, $stdoutf file gets data. run command not output data:
diff -r "$source" "$target" > >(tee "${stdoutf}") 2> >(tee "${stderrf}" >&2) however, doesn't process finishes before test emptiness run (using shunit-ng):
assertnull 'unexpected output stdout' "$(<"$stdoutf")" in 100 run test failed 25 times.
should sufficient call sync before testing file emptiness:
sync assertnull 'unexpected output stdout' "$(<"$stdoutf")" ... and/or should work forcing sequence of commands:
diff -r "$source" "$target" \ > >(tee "${stdoutf}"; assertnull 'unexpected output stdout' "$(<"$stdoutf")") 2> >(tee "${stderrf}" >&2) ... and/or possible tee somehow assertnull directly instead of file?
update: sync not answer - see gilles' response below.
update 2: discussion taken further save stdout, stderr , stdout+stderr synchronously. answers!
in bash, process substitution substitution command foo > >(bar) finishes foo finishes. (this not discussed in documentation.) can check with
: > >(sleep 1; echo a) this command returns immediately, prints a asynchronously 1 second later.
in case, tee command takes 1 little bit of time finish after command completes. adding sync gave tee enough time complete, doesn't remove race condition, more adding sleep would, makes race more unlikely manifest.
more generally, sync not have internally observable effect: makes difference if want access device filesystems stored under different operating system instance. in clearer terms, if system loses power, data written before last sync guaranteed available after reboot.
as removing race condition, here few of possible approaches:
explicitly synchronize substituted processes.
mkfifo sync.pipe command > >(tee -- "$stdoutf"; echo >sync.pipe) 2> >(tee -- "$stderrf"; echo >sync.pipe) read line < sync.pipe; read line < sync.pipeuse different temporary file name each command instead of reusing
$stdoutf,$stderrf, , enforce temporary file newly created.give on process substitution , use pipes instead.
{ { command | tee -- "$stdoutf" 1>&3; } 2>&1 \ | tee -- "$stderrf" 1>&2; } 3>&1if need command's return status, bash puts in
${pipestatus[0]}.{ { command | tee -- "$stdoutf" 1>&3; exit ${pipestatus[0]}; } 2>&1 \ | tee -- "$stderrf" 1>&2; } 3>&1 if [ ${pipestatus[0]} -ne 0 ]; echo command failed; fi
- Get link
- X
- Other Apps
Comments
Post a Comment