I have a file whose content is PID
Tab STARTTIME
and I would like to know if that process is still alive.
I can check that a given PID is running with:
kill -0 "$pid" && echo alive
But it lacks the ability to differentiate between the real process and an other one that got the same PID.
So I though of using ps
:
ps -o lstart= -p "$pid"
But it errputs:
ps: unknown output format: -o lstart
Is there a POSIX way to get the starting time (in seconds since EPOCH) of a given PID from the shell?
As @Cyrus pointed out, it's possible to use the output of ps -o etime=
to calculate the starting time of a given PID:
edit: as @KamilCuk suggested, the functions now use a shell pipe instead of dealing with the ps
call from inside awk
.
# usage: starttime PID
starttime() {
command -p ps -o etime= -p "$1" |
command -p awk '
BEGIN { srand(); timeofday = srand() }
END {
if (NF) {
n = split($NF, a, "[:-]")
print timeofday - a[n-3]*86400 - a[n-2]*3600 - a[n-1]*60 - a[n]
} else
exit 1
}
'
}
But it's more like an approximation, because when I compare it to the starting "date" provided by ps -o lstart=
in Linux, I don't get identical results; as shown by the following script that outputs both values for all the running processes:
#!/bin/bash
starttime() { ... }
while read pid lstart
do
t1=$(date -d "$lstart" +%s) &&
t2=$(starttime "$pid") &&
printf '%s\t%s\n' "$t1" "$t2"
done < <(
ps -o pid= -o lstart= -e
)
1681318132 1681318133
1681133418 1681133419
1681133418 1681133418
1681318132 1681318132
...
While the results are certainly different, the difference doesn't exceed 1 second; therefore, I think that we can still use ps -o etime=
for checking that a process is alive in an environment that doesn't require much precision (for ex. a cron job). Here's a function that "allows" a ±1 second delta:
tested on AIX/Solaris/macOS/FreeBSD/Linux
# usage: is_alive PID STARTTIME
is_alive() {
command -p ps -o etime= -p "$1" |
command -p awk -v starttime="$2" '
BEGIN { srand(); timeofday = srand() }
END {
n = split($NF, a, "[:-]")
d = starttime - timeofday + a[n-3]*86400 + a[n-2]*3600 + a[n-1]*60 + a[n]
exit( -1 < d || d > 1 )
}
'
}