1. Overview

The Linux Operating system generates a PID for each process. In this quick tutorial, let’s explore how to get the process name by a given PID.

2. Introduction to the Problem

As usual, let’s understand the problem by an example.

First, let’s create a simple shell script to simulate a long-running process:

$ cat long-running.sh
#!/bin/bash
echo "PID of $0: $$"
echo "Parameter: $1"
watch -n 300 date > /dev/null

As we can see, we first print the PID of the current script by reading the special variable $$. Then, we tell the watch command to execute the date command every 300 seconds and discard the output.

In this way, we can know its PID when we start the script. Further, it runs as a “long-running” process:

$ ./long-running.sh PARAM
PID of ./long-running.sh: 407203
parameter: PARAM

Now, assuming we only know this PID, we would like to figure out which process is running with this PID.

Of course, our expected result is the long-running.sh script. Next, let’s see how to find the process.

3. Using the ps Command

The ps command is the standard tool to check current processes’ status in the Linux command line.

Further, we can pass the -p option to the ps command to get only the information of the given process, for example:

$ ps -p 407203 
    PID TTY          TIME CMD
 407203 pts/3    00:00:00 long-running.sh

As the output above shows, we’ve seen the expected process name in the CMD column. We can also adjust the ps command’s -o option to ask ps to output only required information.

For example, we can pass “-o comm” to the ps command to get the name of the program only:

$ ps -p 407203 -o comm
COMMAND
long-running.sh

If we want to know the entire command line that was used to start the given process, we can pass “-o command” to ps:

$ ps -p 407203 -o command
COMMAND
/bin/bash ./long-running.sh PARAM

As the output shows, this time, the ps command reports the complete command, including parameters used to start the process.

Sometimes, we want to suppress the column header, for example, “COMMAND” in the output above, so that we can easily pass the result to other programs to do further processing.

To suppress the header from the ps output, we can simply add the “=” character after the -o ColumnName option:

$ ps -p 407203 -o command=
/bin/bash ./long-running.sh PARAM

4. Reading Files Under the /proc/ Directory

The /proc directory is present on all Linux distributions. This directory is a virtual file system. The /proc directory contains details about processes and other system information such as kernel, memory usage, CPU data, and configuration parameters. The operating system mounts /proc at boot.

Each process has a subdirectory under the /proc directory named with its PID. For example, if we want to check the information of the process 407203, we can enter the /proc/407203 directory. There are many “files” under each /proc/ directory. Those files hold detailed information about the process:

$ ls /proc/407203  
arch_status        cwd@    maps            pagemap          stat
attr/             environ    mem           personality   statm
...
exe@ ...
cmdline             io        ns/           sessionid     timers
comm ...

We can read three files to gain the name or the command line of the process: comm, exe, and cmdline. Next, let’s see them in action.

To get the program name of a process, we can read the comm file:

$ cat /proc/407203/comm
long-running.sh

The exe file is a symbolic link. It links to the real command file to start the process:

$ ls -l /proc/407203/exe 
lrwxrwxrwx 1 kent kent 0 Apr 26 09:20 /proc/407203/exe -> /usr/bin/bash

As our process is a shell script, which is always started by the shell, the exe file will merely link to the shell command, which is /usr/bin/bash in this case. However, if our process is started by a regular program, the exe file will point to the executable:

$ ls -l /proc/437301/exe 
lrwxrwxrwx 1 kent kent 0 Apr 26 09:17 /proc/437301/exe -> /usr/bin/vim

The example above shows a vim process.

However, if we would like to know the complete command that started the process along with its parameters, we can check the cmdline file:

$ cat /proc/407203/cmdline 
/bin/bash./long-running.shPARAM

As the output above shows, the shell command, script name, and the script parameter are printed, but they are joined together without separators.

Actually, the output is separated by null characters. We can see them if we pass the -A option (display all) to the cat command:

$ cat -A /proc/407203/cmdline
/bin/bash^@./long-running.sh^@PARAM^@

This time, we can see that the null characters are represented as ‘*^@*‘.

We can use the tr command to reformat the output. For example, we can replace all null characters with spaces:

$ cat /proc/407203/cmdline | tr '\0' ' '
/bin/bash ./long-running.sh PARAM

5. Conclusion

In this quick article, we’ve explored how to get the name and the command line of a given PID in the Linux command line.

The ps -p command is pretty straightforward to get the process information of a PID. Alternatively, we can also access the special /proc/PID directory to retrieve process information.