A recommended way to acquire a lock in Bash is to open the lock file for a group command, and call flock on the open descriptor before doing anything dangerous:
{ echo waiting flock -x 9 echo in sleep 10 echo done } 9> /tmp/lock
Try it in two independent terminals. The second command will run only as the first finishes.
However, one should never have to pick an arbitrary file descriptor (9 in this case). Fortunately, you can get Bash to choose an available descriptor, using {var}
in place of the literal descriptor number:
unset lfd { echo waiting flock -x $lfd echo in sleep 10 echo done } {lfd}> /tmp/lock
Problem solved!
No, wait. The descriptor doesn't get closed at the end of the group command, so your second invocation will hang indefinitely. Once the first terminal has finished, if you manually close the descriptor, the second proceeds:
exec {lfd}>&-
Looks like you have to do things more explicitly (and the group command is no longer useful):
echo waiting unset lfd exec {lfd}> /tmp/lock flock -x $lfd echo in sleep 10 echo done exec {lfd}>&-
This is inconvenient if you want to break or continue out of an enclosing loop:
for i in $(seq 1 10) do { echo waiting flock -x 9 echo in sleep 5 if something_went_wrong ; then continue ; fi sleep 5 echo done } 9> /tmp/lock done
Is this a bug, a feature, or a mistake on my part? (Bash version 4.4.20(1)-release.)
No comments:
Post a Comment