Command the Command Line

Part IV - Managing Systems

Process Management II

Previously, we looked at a few ways to interact with running processes. Those are only applicable in cases where we had created the process in the current shell. That detail makes those methods inappropriate for the majority of system administration tasks. In most cases, we'll need to interact with processes created by other users and often without the aid of a shell.

Lucky for us, there are plenty of powerful tools for inspecting and managing processes.

ps

Display process status

vm$ ps
  PID TTY          TIME CMD
 1892 pts/0    00:00:00 bash
 1926 pts/0    00:00:00 ps
vm$ 

ps is a utility for listing information about active processes. By default, it lists only those processes associated with the same user and terminal of the invoker.

This isn't particularly useful, though--here, ps is verifying that we are running bash and ps itself.

vm$ ps -u
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
vagrant   1892  0.0  0.7  21300  3756 pts/0    Ss   17:31   0:00 -bash
vagrant   1925  0.0  0.2  17168  1272 pts/0    R+   17:33   0:00 ps -u
vm$ 

With the -u option, we can begin to appreciate the utility of this application. We can see information on the process owner, its resource consumption, and even when it was executed.

We won't go in to all the details here; check out the man page for ps for an exhaustive overview.

vm$ ps -aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.5  33600  2920 ?        Ss   17:30   0:00 /sbin/init
root         2  0.0  0.0      0     0 ?        S    17:30   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    17:30   0:00 [ksoftirqd/0]
root         4  0.0  0.0      0     0 ?        S    17:30   0:00 [kworker/0:0]
root         5  0.0  0.0      0     0 ?        S<   17:30   0:00 [kworker/0:0H]
root         6  0.0  0.0      0     0 ?        S    17:30   0:00 [kworker/u2:0]
root         7  0.0  0.0      0     0 ?        S    17:30   0:00 [rcu_sched]
root         8  0.0  0.0      0     0 ?        S    17:30   0:00 [rcuos/0]
root         9  0.0  0.0      0     0 ?        S    17:30   0:00 [rcu_bh]
root        10  0.0  0.0      0     0 ?        S    17:30   0:00 [rcuob/0]
root        11  0.0  0.0      0     0 ?        S    17:30   0:00 [migration/0]
root        12  0.0  0.0      0     0 ?        S    17:30   0:00 [watchdog/0]
root        13  0.0  0.0      0     0 ?        S<   17:30   0:00 [khelper]
root        14  0.0  0.0      0     0 ?        S    17:30   0:00 [kdevtmpfs]
root        15  0.0  0.0      0     0 ?        S<   17:30   0:00 [netns]

When used together, the options -aux give us a much more detailed synopsis of all the processes running on the system. This is just a partial list, but we can see that many of the processes are actually owned by the "root" user.

vm$ ps -aux | grep sleep
vagrant   2079  0.0  0.1   5916   616 pts/0    S    18:31   0:00 sleep 3000
vagrant   2083  0.0  0.1  10464   892 pts/0    S+   18:31   0:00 grep sleep
vm$ 

Searching through that list can be a little tough, so grep may come in handy. Because the search pattern appears within the grep command itself, a naive search will include a false positive. It's not a serious problem, but it can be a little confusing.

vm$ ps -aux | grep slee[p]
vagrant   2079  0.0  0.1   5916   616 pts/0    S    18:31   0:00 sleep 3000
vm$ 

A common trick is to express the search query in terms of a regular expression. The pattern slee[p] matches sleep (the name of the process we're after), but not slee[p] (the option we passed to the grep utility).

PIDs

One important column that has been present in all the ps output we've seen so far is the "PID". This is short for process identifier. Most process management utilities recognize PIDs as references to processes.

kill

Send a signal to a process by PID

vm$ ps -aux | grep slee[p]
vagrant   2079  0.0  0.1   5916   616 pts/0    S    18:31   0:00 sleep 3000
vm$ kill 2079
[1]+  Terminated              sleep 3000
vm$ ps -aux | grep slee[p]
vm$ 

kill is a utility for sending signals to a process. By default, it sends the "SIGTERM" signal. Most applications will respond to this signal by exiting "gracefully."

vm$ sleep 1000 &
[1] 2526
vm$ ps
  PID TTY          TIME CMD
 1892 pts/0    00:00:00 bash
 2526 pts/0    00:00:00 sleep
 2527 pts/0    00:00:00 ps
vm$ kill -s sigint 2526
[1]+  Interrupt               sleep 1000
vm$ ps
  PID TTY          TIME CMD
 1892 pts/0    00:00:00 bash
 2529 pts/0    00:00:00 ps
vm$ 

This is actually the second time we have run across signals in Unix-like systems. Remember that Ctrl+C sends a SIGINT, or "interrupt" signal. We can do the same thing for any process using kill.

vm$ ps
  PID TTY          TIME CMD
 1892 pts/0    00:00:00 bash
 2698 pts/0    00:00:03 rogue-process
 2699 pts/0    00:00:00 ps
vm$ kill 2698
vm$ ps
  PID TTY          TIME CMD
 1892 pts/0    00:00:00 bash
 2698 pts/0    00:00:03 rogue-process
 2701 pts/0    00:00:00 ps
vm$ kill -s sigkill 2698
[1]+  Killed                  rogue-process
vm$ ps
  PID TTY          TIME CMD
 1892 pts/0    00:00:00 bash
 2703 pts/0    00:00:00 ps
vm$ 

Since programs may respond to the (default) SIGTERM signal and the SIGINT signal however they wish, those signals may not always end the process. "stubborn" processes can be reliably cancelled via the SIGKILL signal.

Unlike SIGTERM, SIGKILL will not give the application an opportunity to exit gracefully. Keep this in mind as it may not be acceptable in all cases.

killall

Send a signal to a process by process name

vm$ ps
  PID TTY          TIME CMD
 1892 pts/0    00:00:00 bash
 2708 pts/0    00:00:00 sleep
 2709 pts/0    00:00:00 sleep
 2710 pts/0    00:00:00 sleep
 2711 pts/0    00:00:00 sleep
 2712 pts/0    00:00:00 ps
vm$ killall sleep
[1]   Terminated              sleep 1000
[2]   Terminated              sleep 1000
[3]-  Terminated              sleep 1000
[4]+  Terminated              sleep 1000
vm$ ps
  PID TTY          TIME CMD
 1892 pts/0    00:00:00 bash
 2714 pts/0    00:00:00 ps
vm$ 

The killall utility allows you to signal processes according to their name. This can be convenient in cases where a program has replicated itself a number of times. A process's name can also be a more convenient "handle" to use as a reference...

vm$ ps
  PID TTY          TIME CMD
 1892 pts/0    00:00:00 bash
 2719 pts/0    00:00:00 bash
 2724 pts/0    00:00:00 ps
vm$ killall -9 bash
Connection to 127.0.0.1 closed.
pc$ 

...just be sure you know exactly which processes will match the name.

top

Display a table of processes

vm$ top
top - 19:50:44 up  2:19,  1 user,  load average: 0.00, 0.01, 0.05
Tasks:  72 total,   1 running,  71 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.3 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem:    501764 total,   364180 used,   137584 free,    53756 buffers
KiB Swap:        0 total,        0 used,        0 free.   131620 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
    1 root      20   0   33600   2920   1492 S  0.0  0.6   0:00.76 init
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd
    3 root      20   0       0      0      0 S  0.0  0.0   0:00.05 ksoftirqd/0
    4 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0
    5 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H
    6 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kworker/u2:0
    7 root      20   0       0      0      0 S  0.0  0.0   0:00.27 rcu_sched
    8 root      20   0       0      0      0 S  0.0  0.0   0:00.45 rcuos/0
    9 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_bh
   10 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcuob/0
   11 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0

Finally, the top utility provides a "live" view of running processes. The output will update on a regular interval, and it accepts various keystrokes for modifying the visualization. You can learn more by pressing ? (that's Shift and the forward slash / key). Similar to the less utility, you may exit by pressing the q key.