4

I have a program running on a remote computer which shouldn't be stopped. I need to track when this program is stopped and immediately execute a command. PID is known. How can I do that?

Michael
  • 5,095
  • 2
  • 13
  • 35

4 Answers4

10

You cannot wait for non-child processes.

Probably the most efficient way in a shell would be to poll using the exit code of kill -0 <pid> to check if the process still exists:

while kill -0 $PID 2>/dev/null; do sleep 1; done

This is both simpler and more efficient than any approaches involving ps and grep. However, it only works if your user has permission to send signals to that process.

Thomas
  • 174,939
  • 50
  • 355
  • 478
  • 1
    I agree that `kill -0` is a good way to check for a running process, with one caveat -- it only succeeds if the current user has permission to send signals to that process. – traal Feb 12 '20 at 09:58
0

Code like this can do the work (to be run on remote computer)

while true 
do
if [ "$(ps -efl|grep $PIDN|grep -v grep|wc -l)" -lt 1 ]
then <exec code>; break
fi
sleep 5
done

It expect the variable PIDN to contain the PID.

P.S. I know the code is ugly and power hungry

EDIT: it is possible to use -p in ps to avoid one grep

while true 
do
if [ "$(ps -p $PIDN|wc -l)" -lt 2 ]
then <exec code>; break
fi
sleep 5
done
Romeo Ninov
  • 6,538
  • 1
  • 22
  • 31
  • 3
    Now sure how portable it would be, but at least on the BSD version of `ps` there's an option `-p` to display only a specific process – ChatterOne Feb 12 '20 at 08:22
  • 1
    @ChatterOne, on linux `ps` you have also `-p` (or `p`) option to select one pid. But on some UNIXes you may not found it. But will add it, thank you for the idea – Romeo Ninov Feb 12 '20 at 08:27
0

Here's a fairly simple way to wait for a process to terminate using the ps -p PID strategy:

if ps -p "$PID" >/dev/null 2>&1; then
    echo "Process $PID is running ..."
    while ps -p "$PID" >/dev/null 2>&1; do
        sleep 5
    done
    echo "Process $PID is not running anymore."
fi

Checking for a process by PID

In general, to check for process ownership or permission to kill (send signals to) a proccess, you can use a combination of ps -p PID and kill -0:

if ps -p "$PID" >/dev/null 2>&1; then
    echo "Process $PID exists!"

    if kill -0 "$PID" >/dev/null 2>&1; then
        echo "You can send signals to process $PID, e.g. with 'kill $PID'"
    else
        echo "You do not have permission to send signals to process $PID"
    fi
else
    echo "Process $PID does not exist."
fi
traal
  • 461
  • 3
  • 7
0

You can use exitsnoop to achieve this.

The bcc toolkit implements many excellent monitoring capabilities based on eBPF. Among them, exitsnoop traces process termination, showing the command name and reason for termination, either an exit or a fatal signal.

   It catches processes of all users, processes in containers,  as  well  as  processes  that
   become zombie.

   This  works by tracing the kernel sched_process_exit() function using dynamic tracing, and
   will need updating to match any changes to this function.

   Since this uses BPF, only the root user can use this tool.

exitsnoop examples:

   Trace all process termination
          # exitsnoop

   Trace all process termination, and include timestamps:
          # exitsnoop -t

   Exclude successful exits, only include non-zero exit codes and fatal signals:
          # exitsnoop -x

   Trace PID 181 only:
          # exitsnoop -p 181

   Label each output line with 'EXIT':
          # exitsnoop --label EXIT

You can get more information about this tool from the link below:


Another option

use this project: https://github.com/stormc/waitforpid

hxysayhi
  • 1,888
  • 18
  • 25