Tutorials > How to monitor and manage processes on Linux

How to monitor and manage processes on Linux

Published on: 22 January 2021

Linux System

Introduction

A Linux server, like any other computer you deal with, runs applications. Each running application can use one or more of the so-called "processes". While Linux manages the low level in the life cycle of processes, on several occasions a sysadmin may need to interact with the operating system to best manage them . 

In this guide, you will learn how to control the processes running on your Linux server and how to manage them. All Linux distributions follow similar process operations.

To perform these operations on your server first connect via an SSH connection. If you haven't done so yet, following our guide is recommended to  connect securely with the SSH protocol. In case of a local server go to the next step and open your server terminal.

How to monitor processes on Linux

top

The best way to monitor the processes running on your Linux server is to use the top command :

$ top
top - 15:14:40 up 46 min,  1 user,  load average: 0.00, 0.01, 0.05
Tasks:  56 total,   1 running,  55 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   1019600k total,   316576k used,   703024k free,     7652k buffers
Swap:        0k total,        0k used,        0k free,   258976k cached

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND           
   1 root      20   0 24188 2120 1300 S  0.0  0.2   0:00.56 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.07 ksoftirqd/0        
   6 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/0        
   7 root      RT   0     0    0    0 S  0.0  0.0   0:00.03 watchdog/0         
   8 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 cpuset             
   9 root       0 -20     0    0    0 S  0.0  0.0   0:00.00 khelper            
  10 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kdevtmpfs  

As shown in the example above, after typing the top command, various information will appear on the screen:

  • In the first line it is possible to see the system time (15:14:40), the time since the server is up (46 min), the users connected via SSH (1 user) and the average load of the server (load average) calculated over the last time span of one minute, five minutes and fifteen minutes;
  • From the second to the fifth line, you will find statistical information about the system, such as the total number of processes (tasks) and their status, the consumption of the CPU and RAM memory of the machine;
  • Below, it is possible to see, one by one, the running processes.

Going back to the example above, see that there are currently 1 process running and 55 processes not running. It is important to specify that, while the active process will consume resources, those in the sleeping phase do not generate any CPU consumption for the system.

htop

An improved version of top is htop , which is available if installed in the repositories. To enable the command, install it via command:

$ sudo apt-get install htop

The new command will provide a more understandable and pleasant presentation of the information to the user. See an example below:

htop
 Mem[|||||||||||           49/995MB]     Load average: 0.00 0.03 0.05 
 CPU[                          0.0%]     Tasks: 21, 3 thr; 1 running
 Swp[                         0/0MB]     Uptime: 00:58:11

 PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command
1259 root       20   0 25660  1880  1368 R  0.0  0.2  0:00.06 htop
   1 root       20   0 24188  2120  1300 S  0.0  0.2  0:00.56 /sbin/init
 311 root       20   0 17224   636   440 S  0.0  0.1  0:00.07 upstart-udev-brid
 314 root       20   0 21592  1280   760 S  0.0  0.1  0:00.06 /sbin/udevd --dae
 389 messagebu  20   0 23808   688   444 S  0.0  0.1  0:00.01 dbus-daemon --sys
 407 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.02 rsyslogd -c5
 408 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.00 rsyslogd -c5
 409 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.00 rsyslogd -c5
 406 syslog     20   0  243M  1404  1080 S  0.0  0.1  0:00.04 rsyslogd -c5
 553 root       20   0 15180   400   204 S  0.0  0.0  0:00.01 upstart-socket-br

Cataloging processes

ps

The top  and  htop commands discussed earlier, provide a nice interface, very much like a task manager, to display some information about the running processes.

But sometimes more effective tools may be needed to monitor running processes. One of them is ps.

If invoked without further specifications, the command only returns the list of processes belonging to the user:

$ ps  
PID  TTY      TIME     CMD
1017 pts/0    00:00:00 bash
1262 pts/0    00:00:00 ps 

Interpreting the screen, it is clear that, at the moment, the only two processes run by the user are bash  (i.e. the command prompt) and ps itself.

For a more complete view of the processes within the system, add the specific "aux" to the command:

$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.2  24188  2120 ?        Ss   14:28   0:00 /sbin/init
root         2  0.0  0.0      0     0 ?        S    14:28   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    14:28   0:00 [ksoftirqd/0]
root         6  0.0  0.0      0     0 ?        S    14:28   0:00 [migration/0]
root         7  0.0  0.0      0     0 ?        S    14:28   0:00 [watchdog/0]
root         8  0.0  0.0      0     0 ?        S<   14:28   0:00 [cpuset]
root         9  0.0  0.0      0     0 ?        S<   14:28   0:00 [khelper]
. . .

This option tells ps to show all processes from all users in a user-friendly format.

For a tree view, where to see the hierarchical structure and relationships between processes, use the command instead:

$ ps axjf

PPID   PID  PGID   SID TTY      TPGID STAT   UID   TIME COMMAND
   0     2     0     0 ?           -1 S        0   0:00 [kthreadd]
   2     3     0     0 ?           -1 S        0   0:00  \_ [ksoftirqd/0]
   2     6     0     0 ?           -1 S        0   0:00  \_ [migration/0]
   2     7     0     0 ?           -1 S        0   0:00  \_ [watchdog/0]
   2     8     0     0 ?           -1 S<       0   0:00  \_ [cpuset]
   2     9     0     0 ?           -1 S<       0   0:00  \_ [khelper]
   2    10     0     0 ?           -1 S        0   0:00  \_ [kdevtmpfs]
   2    11     0     0 ?           -1 S<       0   0:00  \_ [netns]
. . .

Paying attention to the information on the screen, it is possible to see that the processes with names preceded by \ _  are "children" of the "parent" process kthreadd .

ID of a process

On Linux and Unix-based systems, each process is assigned an ID or PID . In this way the processes are identified by a unique number and tracked by the system. Find the process ID in the first "PID" column of the results shown above.

The ID of a process can be immediately gotten, also by using the pgrep command followed by the name of the process you are interested in:

$ pgrep bash

1017

In the example, using pgrep with the process name relative to the command prompt, we will be returned the ID 1017.

The first process that runs at system startup, called init , will have an ID of 1.

$ pgrep init

1

The main init process is responsible for deploying all the other processes on the system. All subsequent processes will have a larger ID number, in ascending order.

The parent of a process is responsible for its deployment on the system. Parent processes are equipped with a PPID  ( Parent Process ID ), that can be seen in the information mirrors of the processes. To recall them, use the main commands seen above.

Each user communication with the system, referring to the processes, always involves a translation between the names of the processes and their ID, which is why the PID is often shown by the services for their management.

Parent-child relationships between processes

Creating a child process takes place in two steps:

  1. fork (), which creates a new address space and copies the resources owned by the parent process  to make them available for the child process ;
  2. exec (), which loads an executable file into the address space and executes it.

If a child process exits before its parent , the former remains as a zombie process until the parent gets completed getting the information from it or tells the kernel that it no longer needs that information.

At the end of this step, the pending process resources are freed. If the parent process happens to die before the child instead, then the init () process will take care of reassigning the surviving process to another process .

Sending signals to processes

Every process in Linux responds to signals. They are messages, sent at the operating system level, asking programs to change or terminate a certain behavior.

Sending signals to processes via the PID

The best way to send signals to a program is with the kill command . Obviously, this command attempts to terminate a process.

The following could be an example on how to use it:

$ kill PID_process

Using this command example, a TERM signal would be sent to the process. This signal is used to ask the process if it can terminate. This allows the program to complete uninterruptible procedures instantly and then free up resources and exit.

If the program does not respond to the signal received via the normal kill command, then force it to close by sending the KILL signal instead of TERM .

$ kill -KILL PID_process

This special signal will not be sent to the program, but to the kernel , which is the "core" of the operating system, which will proceed to interrupt the affected process. Forcing the termination of a process is recommended only when facing a program that tends to ignore the TERM request .

Signals are also identified by numerical values ​​so, in case of need, ithe kill command, for example, can be associated with the string -15 instead of -TERM or the string -9 instead of -KILL .

Sending signals for other purposes

The kill command is not only used to send signals to request the stop of processes, but can be used to make you interact in other ways with different programs.

It is possible, for example, to give a HUP  ( hang-up ) signal to ask a program to restart.

For an example, try Apache, which follows the behavior of many programs:

$ sudo kill -HUP PID_Apache

To know the list of all the signals that can be sent using the kill command , just enter the string:

$ sudo kill  -1

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
. . .

As you can see from the output, you will receive both the numerical values ​​and the names of the signals that can be associated with the command to send different types of signals.

Sending signals to processes by name

Aside from the PID, it is also possible tosend signals can be sent to processes using their names. To do so, use the pkill command followed by the name of the process involved:

$ pkill -9 ping

By translating the example string, a force quit command will have been sent to the process named ping .

The same command is equivalent to the string:

$ pkill -9 ‘pgrep ping’

If instead you want to interact with every instance of a process (for example with all running instances of Firefox), just use the killall command as in the example:

$ killall firefox

For example, sending a TERM via the killall command would terminate all active instances of Firefox.

Manipulating process priorities

In a server environment, adjust the priority assigned between the different processes: some may need more resources or time priority, while others may run later.

Linux manages the priority system through the niceness command .

Depending on the consumption of resources, a program is considered less attractive , as it is more "selfish" in the consumption of resources, or prettier , since it is more "generous" in saving resources that can be dedicated to other processes. Usually, the former have higher priority compared to the others that have a lower one.

Looking back at the top command example, you will notice a column named NI. This is the nice value of the process.

$ top
Tasks:  56 total,   1 running,  55 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
Mem:   1019600k total,   324496k used,   695104k free,     8512k buffers
Swap:        0k total,        0k used,        0k free,   264812k cached

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND           
1635 root      20   0 17300 1200  920 R  0.3  0.1   0:00.01 top                
   1 root      20   0 24188 2120 1300 S  0.0  0.2   0:00.56 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.11 ksoftirqd/0

The range of nice values can be from -19 / -20  (highest priority) to 19/20 (lowest priority).

To run a program with a certain value, simply use the nice command :

$ nice -n 15 command_to_execute

The above string can only work when a new program is started.

If, on the other hand, changing the priority value of an already running program is needed, use the renice command .

$ renice 0 PID_process

NB While the nice command can be combined with process names, the renice command necessarily works with PIDs.

Conclusions

Process management on Linux is a topic that sometimes puts new users in difficulty, due to the difference in using tools via terminal compared to those with a graphical interface.

Even if the syntax of the commands can be difficult at first, knowing how to work with the terminal remains a must-have skill  in order to better monitor the progress of processes on your server. By practicing and repeating, these operations will gradually become more intuitive and spontaneous.