Wednesday, April 24, 2013

Mastering the Linux Shell : Killing Processes and Dire Warnings

Today's
installment of Mastering the Linux Shell comes with a warning.
Actually, it comes with a few warnings. .And a viewer advisory. Well,
actually a reader advisory.
You see, some of what I cover sounds pretty violent and discretion is
advised. I'll be talking about processes and their children, and the
need, at times to kill a process. You may even have to kill child
processes so this is not for the squeamish. If it makes you feel any
better, these processes are just code running somewhere in memory. It's
not like Tron
at all. They're just bits of information and when you power off your
machine, they die anyway. I should point out that many long time Linux
users never power their down their machines. Most people think it's
because you really don't need to shut down or reboot Linux systems all
that often. For some, however, it's because they can't bear to kill
processes.
Enough silliness. On to the serious stuff.

Killing Processes

When we talk about killing a process, the common understanding is
that you end the process. The program is closed and no longer running.
That can be one way you kill processes, but there's more to it than
that. You can usually interrupt a foreground process with the Control-C
sequence but that does not work with background processes. The command
used to terminate a process is called kill, which as it turns out, is an unfortunate name for a command which does more than just terminate processes. By design, kill sends signals to jobs. That signal is sent as an option (after a hyphen) to a process ID. The process ID can be found using the ps command as I demonstrated in an earlier article.

kill –signal_no PID

For instance, I can send the SIGHUP signal to process 7612 like this.

kill –1 7612

Signals are messages. They are usually referenced numerically, as with the ever popular “kill –9”
signal, but there are a number of others. The ones you are most likely
to use are 1, 9, and 15. These signals can also be referenced
symbolically with these names.
Signal 1 is SIGHUP. This is normally used with
system processes such as inetd and other daemons. With these types of
processes, a SIGHUP tells the process to hang up, reread its
configuration files, and restart. Most applications will just ignore
this signal.
Signal 9 is SIGKILL, an unconditional termination of the process. Some admins I've known call this “killing with extreme prejudice”.
The process is not asked to stop, close its files, and terminate
gracefully. It is simply killed. This should be your last resort
approach to killing a process and works 99% of the time. Only a small
handful of conditions will ever ignore the -9 signal.
Signal 15, the default, is SIGTERM, a call for normal program termination. The system is asking the program to wrap it up and stop doing whatever it was doing.
Remember when we suspended a process earlier using Control-Z? That
was another signal. Try this to get a feel of how this works. If you
are running in an X display, start a digital xclock with a seconds display updated every second.

xclock -digital -update 1 &

You should see the second digits counting away. Now, find its process ID with “ps ax | grep xclock”. We’ll pretend the process ID is 12136. Let’s kill that process with a “SIGSTOP”.

kill SIGSTOP 12136

The digits have
stopped incrementing, right? Here's a cool trick. Try closing the
window for the xclock by clicking on the x in the corner. It doesn't
work, does it? I'll let you think about that one. For now, let’s restart
the xclock.

kill SIGCONT 12136

As you can see, kill
is probably a bad name for a command that can suspend a process, then
bring it back to life. For a complete list of signals and what they do,
look in the man pages with this command.

man 7 signal

If you wanted to kill a
process by specifying the symbolic signal, you would use the signal name
minus the SIG prefix. For instance, to send the -1 signal to cupsd, I
could do this instead.

kill -HUP `pidof cupsd`

Note that these are back-quotes around the command string above. The pidof command does exactly what you think; it returns the PID of the cupsd daemon.

Dire Warnings

Since I've gone told you about terminating processes, it seems
fitting that I revisit another, much earlier topic, where I discussed
deleting files. When killing processes, you want to be very careful.
Some processes, when terminated, will terminate your entire desktop
session, your network connection, or the entire running machine. Look
for the process you need to terminate, then act accordingly. When
operating as the superuser (i.e. the 'root' user), you can do anything
and the system naturally assumes you know what you are doing. It's true
when dealing with processes and it's true when deleting files.
I've used the explanation that everything on your Linux system is a
file, but then I also said that there were different types of files. In
order to work with directory files, we have the following batch of
commands which are ideally suited to this.

pwd (Print Working Directory)
cd (Change to a new Directory)
mkdir (MaKe or create a new DIRectory)
mv (MoVe directories, or like files, rename them)
rmdir (ReMove or delete DIRectories.)

One way to create a complicated directory structure is to use the mkdir to create each and every directory.

mkdir /dir1
mkdir /dir1/sub_dir
mkdir /dir1/sub_dir/yetanotherdir

What you could do instead is save yourself a few keystrokes and use the "-p" flag instead. This tells "mkdir"
to create any parent directories that might not already exist. If you
happen to like a lot of verbiage from your system, you could also add
the "--verbose" flag for good measure.

mkdir –p /dir/sub_dir/yetanotherdir

To rename or move a directory, the format is the same as you used with a file or group of files. Use the mv command.

mv path_to_dir new_path_to_dir

Removing a directory can be just a bit more challenging. The command "rmdir" seems simple enough. In fact, removing this directory was no problem.

$ rmdir trivia_dir

Removing this one, however, gave me this error.

$ rmdir junk_dir
rmdir: junk_dir: Directory not empty

You can only use rmdir to remove an empty directory. There is a "-p" option
(as in parents) that lets you remove a directory structure. For
instance, you could remove a couple of levels like this.

$ rmdir –p junk_dir/level1/level2/level3

All
the directories from junk_dir on down will be removed, but only if they
are empty of files. This is where it gets interesting. And dangerous.
The better approach is to use the rm command with the "-r", or recursive option. Unless you are deleting only a couple of files or directories, you will want to use the "-f" option as well.

$ rm –rf junk_dir

And now, the DIRE WARNING!

Beware the "rm –rf *" command! Better yet. Never use it.
If you must delete a whole directory structure, change directory to the
one above it and explicitly remove the directory. This is also the
first and best reason to do as much of your work as possible as a normal
user and not root. Since root is all powerful, it is quite capable of
completely destroying your system. Imagine that you are in the top
level directory ( / ) instead of /home/myname/junkdir when you initiated that recursive delete. It is far too easy to make this kind of mistake. Beware.
With that last bit of warning, I leave you until the next instalment.
Many thanks to all of you who have followed me in this series. As
usual, if you wish to comment, please do so here on Google Plus or over here on Facebook and add me to your circles or friend list if you haven't already done so. Also, make sure you sign up for the mailing list over here so that you're always on top of what you want to be on top of. Until next time . . .A votre santé! Bon appétit!