Tuesday, May 6, 2008

Custom Kill Terminal Command

So a program has froze, and you happen to have a terminal handy. Usually, you'd have to do some command to find the Process ID (PID), such as ps -A or top. Then after finding the process ID you'd use the kill [process id] command to kill it. This is usually an annoying task if you have to repeat it alot, an example is shown below:
jake@jakswa-laptop:~$ ps -A
14063 ? 00:00:03 notification-da
17215 ? 00:00:03 pidgin
19981 ? 00:22:14 rhythmbox
24794 ? 00:03:40 firefox
26655 ? 00:00:00 sh
26656 ? 00:00:00 gnome-terminal
26658 ? 00:00:00 gnome-pty-helpe
26659 pts/0 00:00:00 bash
26768 pts/0 00:00:00 ps
jake@jakswa-laptop:~$ kill 24794

However, wouldn't it be nice to just say "killname firefox" and have something automate that process? You CAN! This n00b is excited, because he just made a script to do it! If you want to understand what I did, you should know about piping outputs of commands, and maybe something about regular expressions.

The Script
ps -A | grep $1 | sed -e "s/ *\([0-9]*\) .*/\1/" | xargs kill

What does this do? I'll explain it step by step.
  1. ps -A lists every process with PID and name.
  2. the first vertical bar sends every line that ps -A prints (like 24794 ? 00:03:40 firefox) as the input to the grep $1 [input] command.
    So, grep ends up being something like:
    echo "24794 ? 00:03:40 firefox" | grep firefox (search "24794..." for "firefox")
    where $1 is replaced by whatever process we want to kill — 'firefox' in this case.
  3. if grep finds every line that has the search term, 'firefox', and 'pipes' it to the Stream EDitor (sed) command (this is done by the second vertical bar).
  4. The sed command filters out only the PID of the line that was sent to it by grep, and passes that PID onto the xargs kill command.
  5. 'xargs' takes the given PID and uses it as the argument in a "kill" command
Making it a Terminal Command
So maybe you'd like to run this script as any other command in the terminal. Well all we have to do is copy the script to the '/bin' folder. Just make sure you're root:
sudo cp [scriptfile] /bin
Now you can run it in the terminal using the name of the script file.
Example (to kill 'firefox' with script as "killname"):
killname firefox

Voila! This might not be the best way to do things, and I doubt the script is very error proof (don't run it as root, or else you might kill some important processes). Mainly, this was made to become more comfortable with bash scripting.


More info on pipelining: Pipeline (Unix) - Wikipedia
More info on regular expressions: Regular Expressions - Wikipedia


trausch.us said...

You might want to check out the "killall" command, which is located in the "psmisc" package. It accomplishes an extremely similar task, without having to get the PID numbers. Try starting "gcalctool" and then do (in a terminal, or in the GNOME Run Command box) "killall gcalctool" and you'll see it die off.

Swajak said...

Indeed! Haha. That's pretty much duplicate functionality it seems.

At least I learned something making mine...*shrug*

trausch.us said...

That's alright, though.

Sometimes, I do wish I didn't know about utilities like that, just so that I would be motivated to write them. Living in the time UNIX was invented had to have been fun, I think. Making ones own tools is a good way to get extra programming practice, too.

Anonymous said...

When I try to get it in the bin folder it returns:
cp: [mycommand]: No such file or directory
Why is this?