1. Overview
In this article, we’ll learn how to look up and manipulate processes in a Linux system.
2. Processes in Linux Systems
A process, also called a task, is the execution of a program. It consists of the code that needs to be executed but also includes things like a program’s counter, CPU’s registers, and stacks holding temporary data.
Moreover, it holds metadata such us the state of the process, its identifier, and an id of the user who started it. Every process, with the exception of the initial one, has a parent process, so we can build and browse a process tree.
3. Listing Processes
Let’s start with listing processes with the ps command. Without any parameters, it will print tasks in the current shell with their identifier and command name.
To see all currently running processes, we can use the -A option, while -l will provide us with a more verbose response, including CPU usage and niceness (discussed later). We can also filter results for things like username or PID and sort the output.
For example, let’s find all processes owned by the root user, sorted by CPU usage:
$ ps -Al -U root --sort=-pcpu
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
1 S 1000 7912 7435 14 80 0 - 324097 futex_ ? 00:01:00 chrome
4 S 0 3585 3449 10 80 0 - 2568814 - ? 00:00:51 java
4 S 1000 7418 6659 9 80 0 - 381459 poll_s ? 00:00:39 chrome
0 R 1000 6935 6884 4 80 0 - 445515 poll_s ? 00:00:18 gnome-shell
1 S 1000 11058 7435 4 80 0 - 216787 futex_ ? 00:00:03 chrome
0 S 1000 7470 7418 3 80 0 - 182462 poll_s ? 00:00:15 chrome
1 S 1000 7620 7435 2 80 0 - 275830 futex_ ? 00:00:12 chrome
4 R 0 6596 6594 2 80 0 - 68789 - tty2 00:00:12 Xorg
[...]
Mind that the ps command on macOS has some differences in the options that we can apply.
4. Finding a Process
Although we could use ps with grep to find the specific process we’re interested in, Linux provides us with a convenient tool to do that — pgrep. For example, we can easily find the PID of the current Chrome process:
$ pgrep chrome
621
5. Killing a Process
We can terminate a process by sending a termination signal. There are a lot of different termination signals in Linux, although most of them aren’t implemented in every application.
Every signal has a name and an associated number, and in most cases, we can use the name and number interchangeably. Here are some of the most important signals — these are widely implemented and exhibit the most consistent behavior:
- SIGINT (2) – synonymous with pressing Ctrl+C in a terminal, it can be ignored by the process
- SIGQUIT (3) – similar to SIGINT but with the ability to produce a core dump
- SIGKILL (9) – forces the process to terminate immediately, can’t be ignored, and gives no time to shutdown gracefully
- SIGTERM (13) – gives the application time to shutdown gracefully and can be ignored; behaves similarly to SIGINT
We can kill a process (or processes) with the basic kill command. It takes the PID of the process and can take a termination signal — by default, it uses SIGTERM. Let’s terminate all ping processes forcefully with SIGKILL:
$ kill -s 9 `pgrep ping`
We can also use convenient pkill command that will look up the PID for us:
$ pkill -9 ping
6. Liveness and Permissions
Like we’ve just seen, we usually use signals to send a message to corresponding processes. However, the zero signal completely breaks this convention. It does not send any message to the specified process:
kill -0 123
Although this command doesn’t send anything to the 123 process, it does check that:
- The specified process is alive
- We have the necessary permissions to send any signal to that process
When the process is alive and we do have permission to send signals, then the kill -0 returns silently with a zero exit status:
$ kill -0 123
$ echo $? # last exit status
0
The zero return value above means that we indeed have permission to send signals to process 123.
On the other hand, if the process isn’t alive or we don’t have permissions to signal it, we’ll get a non-zero exit status:
$ kill -0 123
kill: kill 123 failed: no such process
$ each $?
1
Similarly, we can send the same signal with pkill. For instance, let’s send a zero signal to a simple Netcat process:
$ nc -l localhost 8080 &
$ pkill -0 --newest nc
$ echo $?
0
Here we’re sending a zero signal to the newest process matched with the text “nc“.
7. Regulating Process Priority
In Linux systems, the priority of processes is determined by their “niceness”. Nice processes are more eager to share resources, so they have lower priority. Likewise, less nice processes don’t want to share resources, so they have higher priority.
By default, every process has niceness equal to 0 on the scale from -20 to 19. If we would like to start a process with non-default niceness of 15, we could do so using the nice command:
$ nice -n 15 ping baeldung.com
If we want to change the niceness of an already running process, we can use the renice command. Mind that in both cases, setting niceness below zero will require using the sudo command or having superuser permissions.
8. Monitoring Processes Using top and htop
If we’d like to get experience more similar to a GUI task manager that allows us to monitor processes continuously, there are terminal applications for that, too.
The first one that we should look at is top. It prints a summary of system resource usage and a real-time list of processes sorted by CPU usage. Also, it allows us to send signals to processes and change sorting parameters, although the interface is not very user-friendly. If we don’t remember some shortcuts, we can always press ‘?’ to summon the help screen.
htop is similar in functionality but better looking, with coloring and vertical scrolling. It provides us with an interface similar to Midnight Commander and should be intuitive enough for us to use without looking at the documentation.
9. Summary
In this article, we learned what processes are in Linux, how to look them up, and how to manipulate them.