1

Sometimes when I wanted to do something like:

long_running_command; second_command

I forget the ; second_command part. If I don't want to interrupt and restart the long_running_command (sometimes it's not possible, other times it has run for a significant time before I discover my mistake and that work would be wasted), I typically do something like

ps aux | grep long_running_command 
while (kill -0 <pid found above>); do sleep 1; done; second_command

(in another terminal)
and while it works, it results in the following error:

kill: kill <pid> failed: no such process

Is there a way to avoid that error, or a better way to schedule second_command shortly after long_running_command finishes.

(I use zsh on Debian Jessie).

3 Answers3

0

Given Debian (Linux), and assuming there's only one long_running_command:

while [ -d /proc/$(pgrep -f 'long_running_command') ]; do sleep 0.1; done;  second_command

Or, if you know the PID:

while [ -d /proc/PID-HERE ]; do sleep 0.1; done; second_command

If it's a common situation:

waitrun() {
  while [ -d /proc/$1 ]; do sleep 0.1; done;
  shift
  "$@"
}
waitrun PIDHERE second_command
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • 2
    Why would you want to execute pgrep in the loop again and again and again...? – Hauke Laging Aug 08 '17 at 00:40
  • Only if you hadn't saved the pid – Jeff Schaller Aug 08 '17 at 01:25
  • "-d" is if file or directory exists, so it would return just "/proc/" if pgrep not found process and will be also true. Your code doesn't work.

    while [ -n "$(pgrep <executed command>)" ]; do sleep 0.1; done; <second command>

    – Dmitry Apr 24 '21 at 18:28
0

Try using the zsh shell's built-in wait command - it'll do the work for you.

% date; sleep 30s &
Tue Aug  8 22:24:07 EDT 2017
[1] 31875
% wait %1; date
[1]  + done       sleep 30s
Tue Aug  8 22:24:37 EDT 2017

You can also use a PID rather than the job-spec above. So,:

% date; sleep 30s &
Tue Aug  8 22:26:04 EDT 2017
[1] 1821
% wait 1821; date
[1]  + done       sleep 30s
Tue Aug  8 22:26:34 EDT 2017

The semantics are the same on bash too.

Thomas
  • 6,362
  • This seems to only work for backgrounded processes in the same shell. In the question I actually said "(in another terminal)", and when I tried this in a nother terminal than my long_running_command, I get something like "wait: pid 4513 is not a child of this shell". – Henrik supports the community Aug 26 '17 at 11:36
0

This code should do the thing. If command not found the loop breaks and executes a second command.

while [ -n "$(pgrep <executed command>)" ]; do sleep 0.1; done; <second command>

Dmitry
  • 188