One very common command line activity is process control.  Linux, and other *nix operating systems come with a host of programs designed to assist with this, and when combined with features of Bash, and other Bash-like shells, the command line provides a comprehensive process control interface.  In this tutorial, we'll cover some of the basics of process control from the command line.  We'll use signals to interact with processes, and cover how to run processes in both the foreground, and background of a single terminal.

Processes can be controlled by signals, which are precisely what they sound like. Some signals, like KILL and STOP, cannot be ignored by processes, however most may be affected by the program's defined handling.

Here are some common signals, their x86 numbers, and a brief description of what they do:

			(2)  SIGINT  - Keyboard (terminal) Interrupt, can usually be sent to foreground process with ^c
			(3)  SIGQUIT - Keyboard Quit, can usually be sent to foreground process with ^\
			(9)  SIGKILL - Terminate the process
			(11) SIGSEGV - Sent by kernel when process generates a segmentation fault
			(18) SIGCONT - Continue stopped process
			(19) SIGSTOP - Stop the process
			(20) SIGSTSP - Keboard Stop, can usually be sent to foreground process with ^z
		

Sending SIGTERM with ^c is common way to terminate, though messily, a running process:

			$ sleep 60
			^c
		

In Bash, the jobs builtin allows you to view what processes have been suspended, for instance by SIGSTSP (^c). They can be resumed in either the foreground (takes control of terminal) or in background (doesn't take control of terminal) using the builtins fg and bg respectively:

			$ sleep 60
			^z
			[1]  + 16254 suspended  sleep 60
			$ jobs
			[1]  + suspended  sleep 60
			$ fg
		

It's also possible to have jobs report the pid of processes with the -l switch, just like what's displayed when we suspend a process:

			$ sleep 60
			^z
			[1]  + 16254 suspended  sleep 60
			$ jobs -l
			[1]  + 16254 suspended  sleep 60
			$ fg
		

Jobs can be started in the background by appending & to the end of the command:

			$ sleep 60 &
			[1] 19934
			$ jobs
			[1]  + running    sleep 60
		

To better illustrate the difference between processes in the foreground and background, let's write a little toy script that reports its pid every so often:

			#!/bin/bash

			# $$ holds the process' pid
			# $1 is the first argument passed ($n is argument n where 0 is the command itself)

			for i in {1..60}; do
			    echo Hey\, $$ here!;
			    sleep $1; 
			done
		

Let's save that in a file called echo.sh and make it executable with chmod like so:

			$ chmod +x echo.sh
		

Now let's try starting echo in the background like we did with sleep. To terminate the program we can bring it to the foreground with fg and then stop it with ^c:

			$ ./echo.sh 3 &
			[1] 23828
			$ Hey, 23828 here!
			Hey, 23828 here!
			...
			$ jobs
			[1]  + running    ./echo.sh 3
			Hey, 23828 here!
			$ fg
			[1]  + 23828 running    ./echo.sh 3
			^c
		

Now let's start two of them, both in the background. Commands can be strung together by seperating them with a ;:

			$ ./echo.sh 2 &; ./echo.sh 3 &
			[1] 25053
			[2] 25054
			Hey, 25053 here!
			Hey, 25054 here!
			...
			$ jobs
			[1]  - running    ./echo.sh 2
			[2]  + running    ./echo.sh 3
			Hey, 25053 here!
			Hey, 25054 here!
			$ fg
			[2]  - 25054 running    ./echo.sh 3
			Hey, 25053 here!
			^C
			$ fg
			[1]  - 25053 running    ./echo.sh 2
			Hey, 25053 here!
			^C
		

A little messy, but interesting!

Kill Command

During administration, the most common way to send a signal to a process that's not in the foreground of the terminal you're working with is to use the kill command. Despite its name, it can do more than just send a SIGKILL.

When only passed a process identifier (pid), kill sends it SIGTERM:

			$ sleep 60 &
			[1] 16840
			$ kill 16840
			[1]  + 16840 terminated  sleep 60
		

If we suspend a process by sending it a SIGSTSP with ^c, and then try to kill it with a SIGTERM, nothing happens:

			$ sleep 10
			^z
			[1]  + 27994 suspended  sleep 10
			$ jobs -l
			[1]  + 27994 suspended  sleep 10
			$ kill 16254
			$ jobs -l
			[1]  + 27994 suspended  sleep 10
		

This is because a stopped process can only be affected by SIGKILL or SIGCONT. Other signals, like SIGTERM, are queued however, and will be delivered to the process upon continuation:

			$ sleep 60
			^z
			[1]  + 29062 suspended  sleep 60
			$ jobs -l
			[1]  + 29062 suspended  sleep 60
			$ kill 29062
			$ jobs -l
			[1]  + 29062 suspended  sleep 60
			$ fg
			[1]  + 29062 continued  sleep 60
			[1]  + 29062 terminated  sleep 60
		

It's possible to achieve the same thing by using %, which in Bash is the special character for job identity. Functionally, it refers to the first job in the jobs list, and can be used by kill instead of a pid:

			$ sleep 60
			^z
			[1]  + 30853 suspended  sleep 60
			$ kill %
			[1]  + 30853 terminated  sleep 60
		

We can send arbitrary signals with kill by either name or number:

			$ sleep 60
			^z
			[1]  + 31122 suspended  sleep 60
			$ kill -9
			[1]  + 31122 killed     sleep 60
			...
			$ sleep 60
			^z
			[1]  + 31516 suspended  sleep 60
			$ kill -KILL
			[1]  + 31516 killed     sleep 60
		

A nicely formatted table of the signals and their corresponding number can be produced by kill with the -L switch. However, because Bash has a builtin called kill that doesn't support -L, we need to specifically run the binary:

			$ /bin/kill -L
 1 HUP      2 INT      3 QUIT     4 ILL      5 TRAP     6 ABRT     7 BUS
 8 FPE      9 KILL    10 USR1    11 SEGV    12 USR2    13 PIPE    14 ALRM
15 TERM    16 STKFLT  17 CHLD    18 CONT    19 STOP    20 TSTP    21 TTIN
22 TTOU    23 URG     24 XCPU    25 XFSZ    26 VTALRM  27 PROF    28 WINCH
29 POLL    30 PWR     31 SYS
		

Notes and Further Reading

  • ps is useful in figuring out what's running and who's running it.
  • pgrep and pkill can be used to either find the pid of a program, or kill a program by pattern.
  • For a very complete overview of available signals, how to use them, caveats and programming information, see (in Linux) the Programmer's Manual entry:
    • man 7 signal
  • The libc manual's section on Job Control Signals is also quite handy!
# Reads: 1665