To put in my 2c, we can boild down Teixeira's solution to:
try_wait() {
# Usage: [PID]...
for ((i = 0; i < $#; i += 1)); do
kill -0 $@ && sleep 0.001 || return 0
done
return 1 # timeout or no PIDs
} &>/dev/null
Bash's sleep
accepts fractional seconds, and 0.001s = 1 ms = 1 KHz = plenty of time. However, UNIX has no loopholes when it comes to files and processes. try_wait
accomplishes very little.
$ cat &
[1] 16574
$ try_wait %1 && echo 'exited' || echo 'timeout'
timeout
$ kill %1
$ try_wait %1 && echo 'exited' || echo 'timeout'
exited
We have to answer some hard questions to get further.
Why has wait
no timeout parameter? Maybe because the timeout
, kill -0
, wait
and wait -n
commands can tell the machine more precisely what we want.
Why is wait
builtin to Bash in the first place, so that timeout wait PID
is not working? Maybe only so Bash can implement proper signal handling.
Consider:
$ timeout 30s cat &
[1] 6680
$ jobs
[1]+ Running timeout 30s cat &
$ kill -0 %1 && echo 'running'
running
$ # now meditate a bit and then...
$ kill -0 %1 && echo 'running' || echo 'vanished'
bash: kill: (NNN) - No such process
vanished
Whether in the material world or in machines, as we require some
ground on which to run, we require some ground on which to wait too.
When kill
fails you hardly know why. Unless you wrote
the process, or its manual names the circumstances, there is no way
to determine a reasonable timeout value.
When you have written the process, you can implement a proper TERM handler or even respond to "Auf Wiedersehen!" send to it through a named pipe. Then you have some ground even for a spell like try_wait
:-)