Managing Processes

This chapter gives a basic overview of process management for interactive usage only. Handling processes for other use cases, such as system administration, requires a more robust solution (see mywiki.wooledge: Process Management to get started for such use cases).


Here are some definitions that will be handy to know for this chapter's contents:

  • Program is a set of instructions written to perform a task
  • Process is any running program
  • Daemon are background processes
  • Job is a process that is not a daemon
    • i.e. jobs are interactive programs under user control

Running jobs in background

Some commands and scripts can take more than few minutes to complete, and you might still need to continue using the shell. If you are not dependent on the current shell environment, you could just open another shell instance and continue working.

Another option is to push the job to the background, either at the time of command invocation itself or after the fact. Make sure to redirect standard output and error to avoid interfering with your continued interactive usage. Appending an & character to the command will execute it in the background.

$ tkdiff ip.txt ip.txt.bkp &
[1] 12726

In the above example, [1] refers to the job number and 12726 is the PID (process ID). You can use the jobs and ps commands to track active jobs:

$ jobs
[1]+  Running                 tkdiff ip.txt ip.txt.bkp &

$ ps
    PID TTY          TIME CMD
   9657 pts/1    00:00:00 bash
  12726 pts/1    00:00:00 wish
  12730 pts/1    00:00:00 ps

But what if you forgot to append & to the command? You can follow these steps:

  • Ctrl+z — suspend the current running job
  • bg — push the recently suspended job to the background
  • continue using shell
  • fg — bring the recently pushed background job to the foreground
    • you can use fg %n to bring the nth job number to the foreground

Here's a demo that you can try:

# sleep for 30 seconds (used here for illustration purposes)
# press Ctrl+z to suspend this job
# you'll get the job number, status and the command in the output
$ sleep 30
[1]+  Stopped                 sleep 30

# bg puts the job considered as the current by the shell to the background 
$ bg
[1]+ sleep 30 &

# use 'jobs' or 'ps' to check list of jobs
# '+' after the job number is used to indicate the current job
$ jobs
[1]+  Running                 sleep 30 &
$ ps
    PID TTY          TIME CMD
   2380 pts/0    00:00:00 bash
   6160 pts/0    00:00:00 sleep
   6162 pts/0    00:00:00 ps

# fg brings the most recently pushed background job to the foreground
$ fg
sleep 30

info jobs, bg and fg are shell builtins. See bash manual: Job Control for more details. See also this tutorial on job control.

info See also I want to run something in the background and then log outscreen, tmux, nohup, disown, etc.


The ps command gives a snapshot of the current processes. A few examples were already seen earlier in this chapter. Here's an example with the -f option (full-format listing):

$ ps -f
UID          PID    PPID  C STIME TTY          TIME CMD
learnby+   12299   12298  0 16:39 pts/0    00:00:00 bash
learnby+   12311   12299  0 16:39 pts/0    00:00:00 ps -f

The fields in the above example are effective user ID (UID), process ID (PID), parent process ID (PPID), processor utilization (C), starting time (STIME), controlling terminal (TTY), cumulative CPU time (TIME) and command with all its arguments (CMD). You can use the -o option to customize the fields you want. The --sort option will help you to sort based on specific fields. See ps manual: Standard Format Specifiers for complete list of formats available.

The -e (or -A) option selects all processes. This option is typically used in combination with grep for filtering:

$ ps -e | grep 'vim'
   6195 ?        00:03:13 gvim

info See also linuxjourney: ps tutorial.


The pgrep command helps you filter processes based on their name and attributes. By default, it matches against the process name, for example:

$ ps -e | grep 'vim'
   2006 ?        00:00:27 gvim
   3992 pts/2    00:00:00 vim

$ pgrep 'vim'

You can use the -l option to display the process name as well (PID is shown by default).

$ pgrep -l 'vim'
2006 gvim
3992 vim

To match the process name exactly (instead of matching anywhere), use the -x option.

$ pgrep -x 'vim'

The -a option will list the full command line (the -l option seen earlier gives only the name, not the arguments).

$ pgrep -a 'vim'
2006 gvim -p notes.txt src/
3992 vim

info There are several more options like filtering based on effective UID, PPID, etc. See pgrep manual for more details.


Sometimes, a process might not be responding to your interaction, might be taking too long, accidentally uses too much memory, and so on. You can use the kill command to manage such processes.

As mentioned at the beginning of this chapter, these examples are suggested for interactive processes initiated by you (other usage, for example in scripts, will require different strategies). Be 100% sure before you attempt to send signals to manage processes.

You can pass signals by name or by their associated number. Use kill -l to get a full list of signals. See also unix.stackexchange: List of Signals and unix.stackexchange: What causes various signals to be sent?

# first 20 signals (out of 64) listed below 
$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP

You can use PID or job number to specify the process to which the signal has to be sent. By default, SIGTERM (15) is sent, which is a polite way to ask the program to terminate. Here's an example:

# 'sleep' is used here to emulate a long running process
# press Ctrl+z to suspend this command
$ sleep 100
[1]+  Stopped                 sleep 100

# terminate job number 1
# by default, SIGTERM is sent
$ kill %1
# just press Enter
[1]+  Terminated              sleep 100

Note that in the above example, pressing Ctrl+z actually sends the SIGTSTP (20) signal. Programs usually handle such signals to find a safer spot to suspend. Pressing Ctrl+c sends the SIGINT (2) signal, usually used to abort a process (depends on how the program handles it). You can use Ctrl+\ to send SIGQUIT (3), typically used to ask the program to quit and give a core dump. See also stackoverflow: gracefully shutdown processes.

Here's an illustration to show how to pass signals by their names and numerical values:

$ sleep 100 &
[1] 10051

# suspend the above job, similar to using Ctrl+z
# -20 refers to the signal number 20, i.e. SIGTSTP
# 10051 is the PID
$ kill -20 10051

[1]+  Stopped                 sleep 100

# resume the job in background
$ bg
[1]+ sleep 100 &

# -s option allows you to specify signal by its name
# '-s SIGTERM' is optional here, since that is the default
$ kill -s SIGTERM 10051
[1]+  Terminated              sleep 100

info warning If you need to terminate a process at all costs, you can use SIGKILL (9). This is a signal that cannot be blocked by programs. Use Ctrl+z to suspend a runaway job and then apply kill -9 instead of trying to abort such jobs using Ctrl+c. See also unix.stackexchange: why kill -9 should be avoided.

info Note that your system will likely have several different implementations of the kill command. The shell builtin version was discussed in this section.


The top command displays processes in a tabular format along with information like PID, process name, memory usage and so on. Here's a sample screenshot:

sample screenshot for the top command

This command opens an interactive session, and automatically updates the information being displayed as well. You can press M (uppercase) to sort the processes by memory usage. Press e repeatedly to display memory sizes in terms of mega/giga/etc. Press h for help and press q to quit the session.

info Press W (uppercase) to write the current settings to the toprc configuration file and quit. The next time you use the top command, it will be displayed in the format that was saved.

info See also alternative implementations like htop and btop.


The free command displays information about your system memory. Here's an example:

# -h option shows the results in human readable format
$ free -h
              total        used        free      shared  buff/cache   available
Mem:          7.6Gi       2.4Gi       2.3Gi       267Mi       2.9Gi       4.7Gi
Swap:         3.6Gi          0B       3.6Gi

Further Reading


1) How would you invoke a command to be executed in the background? And what would you do to push a job to the background after it has already been launched? What commands can you use to track active jobs?

2) What do + and - symbols next to job numbers indicate?

3) When would you use fg %n and bg %n instead of just fg and bg respectively?

4) Which option will help you customize the output fields needed for the ps command?

5) What's the difference between pgrep -a and pgrep -l options?

6) If the job number is 2, would you use kill %2 or kill 2 to send SIGTERM to that process?

7) Which signal does the Ctrl+c shortcut send to the currently running process?

8) Which command helps you to continuously monitor processes, along with details like PID, memory usage, etc?

9) Which key will help you manipulate kill tasks from within the top session?

10) What does the free command do?