Say I have a pid in hand, mypid=$$
is there some bash/system command I can use to listen for the exit of that process with the given pid?
If no process with mypid exists, I guess the command should simply fail.
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityI got what I needed from this answer: https://stackoverflow.com/a/41613532/1223975
..turns out using wait <pid>
will only work if that pid is a child process of the current process.
However the following will work for any process:
Linux:
tail --pid=$pid -f /dev/null
Darwin (requires that $pid
has open files):
lsof -p $pid +r 1 &>/dev/null
Linux:
timeout $timeout tail --pid=$pid -f /dev/null
Darwin (requires that $pid
has open files):
lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)
tail
is available to install via homebrew on macOS (Darwin), and becomes available as gtail
. apple.stackexchange.com/a/69332. Is tail --pid
preferable over lsof -p
?
The portable way is to poll using kill, i.e. something like:
until kill -s 0 "$pid" 2>/dev/null; do sleep 1; done
This doesn't require non-portable commands such as GNU tail or lsof, and, in bash, only invokes one external command, namely sleep. GNU tail is likely a bit more efficient, since it was written in C (and could, in theory, take advantage of advanced functions such as pidfd_open
), and lsof is likely going to have a lot of overhead.
A rough timeout can be implemented by counting the number of loop iterations.
A slightly less portable solution that only works for one waiter is to use ptrace(2), which doesn't have a portable shell interface, but which can be accessed using the strace command on some systems:
strace -e exit -e signal=none -p "$pid"
until
as an equivalent (and slightly more portable as !
is not Bourne) of while !
. And kill -s 0
as the POSIX equivalent of POSIX+XSI kill -0
.
Dec 29, 2020 at 15:38
gtail
after you install coreutils via homebrew (works even on M1 Mac): apple.stackexchange.com/a/69332. Are we sure if tail is much more efficient for the job compared to lsof? am not a unix/linux expert.
strace -p <PID>
works for me. It even shows wait()
with child process exit status.
You can use the bash builtin wait
:
$ sleep 10 &
[2] 28751
$ wait 28751
[2]- Done sleep 10
$ help wait
wait: wait [-n] [id ...]
Wait for job completion and return exit status.
Waits for each process identified by an ID, which may be a process ID or a
job specification, and reports its termination status. If ID is not
given, waits for all currently active child processes, and the return
status is zero. If ID is a a job specification, waits for all processes
in that job's pipeline.
If the -n option is supplied, waits for the next job to terminate and
returns its exit status.
Exit Status:
Returns the status of the last ID; fails if ID is invalid or an invalid
option is given.
It uses the system call waitpid()
..
$ whatis waitpid
waitpid (2) - wait for process to change state
bash: wait: pid 47760 is not a child of this shell
...back to the drawing board lol
Feb 28, 2018 at 8:22
Regarding the https://stackoverflow.com/a/41613532/1223975 solution that Alexander Mills reposted, Timeout in Seconds
Darwin
, is a workaround for a UNIX-like OS that does not have GNU tail
. It is not specific to Darwin
, but, depending on the age of the UNIX-like operating system, the command-line offered is more complex than necessary, and can fail:
lsof -p $pid +r 1m%s -t | grep -qm1 $(date -v+${timeout}S +%s 2>/dev/null || echo INF)
On at least one old UNIX, the lsof
argument +r 1m%s
fails (even for a superuser):
lsof: can't read kernel name list.
The m%s
is an output format specification. A simpler post-processor does not require it. For example, the following command waits on PID 5959 for up to five seconds:
lsof -p 5959 +r 1 | awk '/^=/ { if (T++ >= 5) { exit 1 } }'
In this example, if PID 5959 exits of its own accord before the five seconds elapses, ${?}
is 0
. If not ${?}
returns 1
after five seconds.
It may also be worth expressly noting that in +r 1
, the 1
is the poll interval (in seconds), so it may be changed to suit the situation.
gtail
after you install coreutils via homebrew (works even on M1 Mac): apple.stackexchange.com/a/69332. The answer unix.stackexchange.com/a/626632/456507 suggests that GNU tail will be more efficient compared to lsof for the job, though idk.
wait
in the shell or thewait()
C library function. There is AFAIK no standard way of waiting for a non-child process. It is further unclear if the C# function can do that (it depends on what an "associated process" is).