The [
command is to evaluate conditional expressions. It's of no use here.
Because umount
doesn't output anything on its standard output (the errors go to stderr), `sudo umount mount`
expands to nothing.
So it's like:
while [ ]
do
sleep 0.1
done
The [
command, when not passed any argument beside [
and ]
returns false (a non-zero exit status), so you will not enter the loop.
Even if umount
had output its errors on stdout, using the [
command would not have made sense, because the words resulting of that output would never have made up a valid conditional expression.
Here you want:
until sudo umount mount
do
sleep 0.1
done
That is, you want to check the exit status of sudo/umount, not of a [
command.
If you wanted to check if umount
output any error or warning on its stderr, that's where the [
could have been useful. The -n "some-string"
is a conditional expression recognised by the [
command to test whether "some-string"
is empty or not, so something like:
while [ -n "$(sudo umount mount 2>&1 > /dev/null)" ]; do
sleep 0.1
done
But looking for the presence of error or warning messages is generally a bad idea. The umount
command tells us whether or not it succeeds with its exit code, that's much more reliable. It could succeed and still output some warning message. It could fail and not output an error (like when it's killed).
In this particular case, note that umount
might fail because the directory is not mounted, and you would loop forever in that case, so you could try another approach like:
while mountpoint -q mount && ! sudo umount mount; do
sleep 0.1
done
Or if "mount" may be mounted several times and you want to unmount them all:
while mountpoint -q mount; do
sudo umount mount || sleep 0.1
done
Best Answer
When
true
exits, the read side of the pipe is closed, butyes
continues trying to write to the write side. This condition is called a "broken pipe", and it causes the kernel to send aSIGPIPE
signal toyes
. Sinceyes
does nothing special about this signal, it will be killed. If it ignored the signal, itswrite
call would fail with error codeEPIPE
. Programs that do that have to be prepared to noticeEPIPE
and stop writing, or they will go into an infinite loop.If you do
strace yes | true
1 you can see the kernel preparing for both possibilities:strace
is watching events via the debugger API, which first tells it about the system call returning with an error, and then about the signal. Fromyes
's perspective, though, the signal happens first. (Technically, the signal is delivered after the kernel returns control to user space, but before any more machine instructions are executed, so thewrite
"wrapper" function in the C library does not get a chance to seterrno
and return to the application.)1 Sadly,
strace
is Linux-specific. Most modern Unixes have some command that does something similar, but it often has a different name, it probably doesn't decode syscall arguments as thoroughly, and sometimes it only works for root.