Twitter

Some bash tips -- 11 -- Unleash your shell power with ... "| bash" !

This blog is part of a bash tips list I find useful to use on every script -- the whole list can be found here.

When interviewing someone for a job, I almost always ask the question: "how would you kill thousands of processes on a system ?". I won't list all the "interesting" answers/ideas I had but so many people are stuck being able to quickly achieve this task which, first of all, happens in real life (here for example) and, secondly, needs to be fixed very quickly when it happens and you have no time to kill all these process one by one manually after some weird copy and paste technic using a spreadsheet tool :)

To start with, let's create some processes we want to kill (I will create only 5 for the purpose of this blog to keep the output visible); let's create some processes sleeping and doing nothing but a real case scenario would be to kill all the processes of an Oracle instance, processes locking a NFS to be umounted (output of lsof), etc ...:
$ for i in {1..5}; do (sleep 3600 &) ; done
$ ps -ef | grep sleep | grep -v grep
fred        21     1  0 21:28 tty1     00:00:00 sleep 3600
fred        23     1  0 21:28 tty1     00:00:00 sleep 3600
fred        25     1  0 21:28 tty1     00:00:00 sleep 3600
fred        27     1  0 21:28 tty1     00:00:00 sleep 3600
fred        29     1  0 21:28 tty1     00:00:00 sleep 3600
$
We now have 5 sleeping processes we want to kill and we know that the second column is the process id (in orange in the above output). We could easily kill them one by one manually as there are only 5 but remember that a real life scenario will be closer to thousands of processes.
The first thing to do here is to generate the kill commands; I will use awk for this purpose (with awk, the $2 variable is the second column of the output -- so the PID we want to kill):
$ ps -ef | grep sleep | grep -v grep | awk '{print "kill "$2}'
kill 21
kill 23
kill 25
kill 27
kill 29
$
OK great, now that we have all the kill commands, we have to execute them with ... | bash! Indeed, by piping a command into bash (or sh), they will be executed. Let's try that out.
$ ps -ef | grep sleep | grep -v grep | awk '{print "kill "$2}' | bash
$ ps -ef | grep sleep | grep -v grep
$     <== no more sleep process, they have all been killed !
Powerful, right ? indeed it is !














Just one thing to keep in mind, remember that with great powers come great responsibility, so be very careful and double check that you grep the good processes you want to kill not to kill too much processes !

Enjoy your new powers !



< Previous bash tip / Next bash tip >

4 comments:

  1. Thank you very much for this post. I learned a new thing today.

    ReplyDelete
  2. 1) never, ever do "... | bash"
    2) pgrep sleep; pkill sleep
    3) ps -e -o pid= -o cmd= | awk '$2 ~ /sleep/ {print $1}' | xargs kill
    4) generally, if you have a complex selection pattern, but get the PIDs in the end, do "... | xargs kill"

    cura ut valeas

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. Could you please clarify "1) never, ever do "... | bash"" ?

      Kill processes works well with xargs but more complex examples may not be that simple if you have many variables in your output. In the oracle world for example, you may have something like:


      crsctl xxxx | awk '{
      ...
      many lines here to get what we want
      ...
      }'


      And have output variables like the ORACLE_HOME, the ORACLE_SID, the database name, a service name, a target node to start a service to, etc ... so it looks easier to me to generate all the code with awk and execute with | bash.

      Regards,

      Delete

CUDA: Getting started on Google Colab

While getting started with CUDA on Windows or on WSL (same on Linux) requires to install some stuff, it is not the case when using Google...