Tuesday, June 1, 2010

Shell scrips to start and stop background processes in Linux

Here I presents an overview of some useful shell scripts for starting and stopping background process, manually, or by other shells or programmes.

To start and stop background processes, in most situations we need their PID (process ID).

To find out the PID of the process
use the command;
ps 

To show all the processes;
ps -A 

To find out the  PID and the PGID (process group ID) of the processes;
ps -o cmd,pid,pgid

To get the PID for the given process name;
pgrep <process name>
e.g 
pgrep bash
 
To
kill the process

To kill the process by process name;
pkill <process name>
e.g. 
pkill java

To kill by PID;
kill -9 <PID>
e.g.
kill -9 12345

To kill by
PGID (process group ID);
kill -9 -<PGID>
e.g. if pgid is 9876, then type as;
kill -9 -9876

To kill process by their process name;
pkill <process name>
e.g.
pkill java

Now we'll move in to background processes. These
processes seems to useful situations like;
  • Other processes want the same terminal to execute them selves.
  • When time consuming processes is executed
  • Several processes need to be started one after other
  • etc

There is a very easy way
to do this in Linux. We just need to add '2>&1 &' at the end of the shell command, where the process will start in the background and immediately returns the terminal back to the user.

e.g. 
./server.sh 2>&1 &
./server.sh > server.log 2>&1 &

Note: If you use '2>&1', the script won't return the terminal, until the processing is over.

But when we start and kill processes pragmatically, we encounter a new challenge. We should kill the exact process that we started, and we
should not kill some other process!!
To do so, we should keep tack of the PID of the processes we started.

In order to get the PIDs, we can add the following code to the shell script that we are running.
To get the PID of the process that is currently running;
echo $$ > server.pid

Or to get the PID of the process,
last started;
echo $! &> server.pid

Well, now we have the PID. Next, we have to kill the processes we stated.
If we only have single processes - which don't have child processes
- we can use a command like;
cat server.pid | xargs -i kill -9 {}

This kills all the processes, who's PIDs in the servers.pid.

But
sometimes we encounter process trees, in this case when we kill the parent process the child process wont just get killed, but it itself will become a parent. In such situations we should kill the whole process tree.

If you want to view the process tree, you can use the command;
ps f

Or for a detailed view;
pstree

Sometimes in background processes, you encounter problems that the child processes wont get killed even we kill the parent process. Therefore to kill the child processes, you can use two approaches.
  1. kill the process tree (recommended)
  2. kill the processes which contains the same PGID (this works because in most cases the whole process tree will have the same process group id (PGID))

Killing the process tree using the parent's PID

you can uses that following shell script;
#!/bin/sh
for i in `ps -ef| awk '$3 == '${$1}' { print $2 }'`
do
echo killing $i
kill -9 $i
done
echo killing $1
kill -9 $1

Save this as 'kill-process-tree.sh'

Give executable permission to the script by the command;
chmod 755 kill-process-tree.sh

Then use the command to run the script;
./kill-process-tree.sh
e.g.
./kill-process-tree.sh 7234

Killing the processes which contains the same PGID

First we need to find out the PGID of the given PID of the process;
echo $! |xargs echo | xargs -i ps -o pgid -p {}|xargs echo |awk '{print $2}' > server.pgid

Then to kill the processes with give PGID use the command;
cat server.pid | xargs -i kill -9 -{}