2

I'm trying to get the PID of a shell script so I can kill it at a later date.

bash "home/lewis/builds/arduino/arduino-1.8.12/arduino" & disown
echo "$!"

The above runs and returns 37977

BUT

when I run kill 37977 I get

bash: kill: (37977) - No such process

I assume this is because the script /home/lewis/builds/arduino/arduino-1.8.12/arduino then spawns other processes which are not 37977.

Is there a way I can get hold of the final PID of a shell script or any other command I run, usually it works a charm but this instance is causing me an issue.

I need a solution that's transferable to other commands in case this happens again.

7
  • Does kill -37977 work?
    – terdon
    Jun 12 '20 at 15:38
  • bash: kill: 37977: invalid signal specification Jun 12 '20 at 15:52
  • 2
    Sorry, that should have been kill -TERM -37977. I am thinking that if you are right and 37977 is the PID of the arduino process which then launches other processes, then those other processes should all be in the same process group, whose PGID should be 37977. If I'm right, kill -TERM -37977 should kill all processes in that process group. Also check the output of ps aux | grep 37977 (before killing anything) to see what's going on. Does it return anything?
    – terdon
    Jun 12 '20 at 15:56
  • 1
    ps axo pgrp,pid,cmd | grep "^ 37977 " will list the processes in the process group 37977.
    – icarus
    Jun 12 '20 at 16:18
  • 1
    @LewisMorris I give you a way (essentially what icarus said) in my answer.
    – terdon
    Jun 12 '20 at 16:30
3

If the spawned process is launching other processes and then exiting, the new processes should all have the same process group ID (PGID) and that should be the PID of the original process (37977 in your example). So what you want is a way of killing all processes in a PGID. This can be done with kill and a negative PID, as explained in man kill:

          -n     where n is larger than 1.  All processes in process group
                 n are signaled.  When an argument of  the  form  '-n'  is
                 given,  and it is meant to denote a process group, either
                 a signal must be specified first, or the argument must be
                 preceded  by a '--' option, otherwise it will be taken as
                 the signal to send.

So, what you're after is:

bash "home/lewis/builds/arduino/arduino-1.8.12/arduino" & disown
kill -TERM -"$!"

If what you need is to collect the list of individual PIDs, you can do:

bash "home/lewis/builds/arduino/arduino-1.8.12/arduino" & disown
ps -eo pgid,pid | awk -v pid=$! '$1==pid{print $2}')

That will return the list of PIDs whose PGID is $!. If your shell supports arrays (bash does), you could even do:

pids=($(ps -eo pgid,pid | awk -v pid=$! '$1==pid{print $2}'))
for pid in "${pids[@]}"; do echo "Killing $pid"; kill $pid; done

Or anything else you need.

2
  • 1
    One day, I hope I have the knowledge of Linux you do. Looking back now, I wish I had ditched windows years ago. So many years wasted. Every few years I would install a distribution only to go back to windows after a few days. But I'm about 6 months in and I don't see myself ever going back now. There is so much to learn, but I am getting there slowly. I appreciate your thorough answer. Jun 12 '20 at 16:40
  • 3
    @LewisMorris you're very welcome. As for learning, just hang out here! Nothing has taught me more about *nix than the time I've spent answering questions or reading answers here!
    – terdon
    Jun 12 '20 at 16:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.