If a process was not started with an absolute path, it is surprisingly difficult to find out the absolute path for the associated executable.
We demonstrate this using Splunk as an example:
$ ps -ef |grep splun[k]d root 7143802 5702116 0 Apr 23 - 23:26 splunkd --nodaemon -p 8089 _internal_exec_splunkd root 31916484 7143802 0 Apr 23 - 0:00 [splunkd pid=7143802] splunkd --nodaemon -p 8089 _internal_exec_splunkd [process-runner] $
When starting the process with the PID 31916484, the argument 0 was also changed.
Part of the information about a process is available via the process file system /proc. Since Splunk runs as root, root privileges are required to access the information in /proc about the process.
Below /proc there is a subdirectory for each running process, with the PID as the directory name.
# ls -l /proc/31916484 total 32 -rw------- 1 root system 0 Apr 28 15:17 as -r-------- 1 root system 128 Apr 28 15:17 cred --w------- 1 root system 0 Apr 28 15:17 ctl lr-x------ 38 root system 0 Apr 28 13:31 cwd -> /root/ dr-x------ 1 root system 0 Apr 28 15:17 fd dr-xr-xr-x 1 root system 0 Apr 28 15:17 lwp -r-------- 1 root system 0 Apr 28 15:17 map -r-------- 1 root system 0 Apr 28 15:17 mmap dr-x------ 1 root system 0 Apr 28 15:17 object -r--r--r-- 1 root system 448 Apr 28 15:17 psinfo lr-x------ 48 root system 0 Apr 28 09:02 root -> / -r-------- 1 root system 12288 Apr 28 15:17 sigact -r-------- 1 root system 1520 Apr 28 15:17 status -r--r--r-- 1 root system 0 Apr 28 15:17 sysent #
In the subdirectory object, in addition to the open files, the executable is also available:
# ls -l /proc/31916484/object total 854216 -r-xr-xr-x 1 root system 194980846 Nov 16 2019 a.out -r-xr-xr-x 1 bin bin 10749 Sep 21 2015 jfs2.10.5.103039 -r--r--r-- 1 bin bin 12858422 May 28 2019 jfs2.10.5.225767 -r-xr-xr-x 1 bin bin 77411 Mar 25 2021 jfs2.10.5.4157 -r-xr-xr-x 1 bin bin 13438344 Jul 27 2021 jfs2.10.5.4205 -r--r--r-- 1 bin bin 1351386 Mar 09 2021 jfs2.10.5.4209 -r--r--r-- 1 bin bin 80450 Jul 27 2021 jfs2.10.5.4220 -r-xr-xr-x 1 root system 194980846 Nov 16 2019 jfs2.10.9.139342 -r-xr-xr-x 1 root system 3487967 Nov 12 2019 jfs2.10.9.155672 -r-xr-xr-x 1 root system 228087 Nov 12 2019 jfs2.10.9.155673 -r-xr-xr-x 1 root system 2688333 Nov 16 2019 jfs2.10.9.155675 -r-xr-xr-x 1 root system 901800 Nov 12 2019 jfs2.10.9.155677 -r-xr-xr-x 1 root system 4256593 Nov 12 2019 jfs2.10.9.155679 -r-xr-xr-x 1 root system 568791 Nov 16 2019 jfs2.10.9.155684 -r-xr-xr-x 1 root system 6166802 Nov 12 2019 jfs2.10.9.155685 -r-xr-xr-x 1 root system 1239656 Nov 12 2019 jfs2.10.9.155686 -r-xr-xr-x 1 root system 124218 Nov 16 2019 jfs2.10.9.155690 #
The file a.out represents the executable. Access to this file is redirected to the executable’s file. Information such as the inode number and device (file system) of the executable can be found with the istat command:
# istat /proc/31916484/object/a.out Inode 139342 on device 10/9 File Protection: r-xr-xr-x Owner: 0(root) Group: 0(system) Link count: 1 Length 194980846 bytes Last updated: Tue Jul 27 07:15:40 CEST 2021 Last modified: Sat Nov 16 01:23:05 CET 2019 Last accessed: Thu Apr 28 10:38:13 CEST 2022 #
The inode number of the executable is 139342. The file system is the file system on the device with major number 10 and minor number 9 (“device 10/9“).
You could now first find out the device by searching under /dev:
$ ls -l /dev | grep "10, 9" brw-rw---- 1 root system 10, 9 Jul 27 2021 hd10opt crw-rw---- 1 root system 10, 9 Apr 05 13:36 rhd10opt $
and then determine the associated file system via df:
$ df | grep hd10opt /dev/hd10opt 12582912 7527920 41% 33349 4% /opt $
However, this is even easier. You can simply specify the path for the a.out file in df:
# df /proc/31916484/object/a.out Filesystem 512-blocks Free %Used Iused %Iused Mounted on /dev/hd10opt 12582912 7527912 41% 33349 4% /opt #
The file system we are looking for is the /opt file system. Now you can find out the absolute path to the executable by searching for the inode number 139342 in /opt:
# find /opt -inum 139342 /opt/splunkforwarder/bin/splunkd #
The process with the PID 31916484 runs the executable /opt/splunkforwarder/bin/splunkd.
With a little trick you can also shorten the search significantly. For this you need a shell as user root. In this shell you open the a.out explicitly with exec and a (free) descriptor number:
# exec 5</proc/31916484/object/a.out #
Our current shell has thus opened the executable (via the file descriptor 5)! Now you can use the procfiles command to display the open files in this shell. Using the “-n” option, which displays the absolute paths of files that belong to a file descriptor:
# procfiles -n $$ 19136808 : ksh Current rlimit: 10000 file descriptors 0: S_IFCHR mode:00 dev:10,4 ino:4463 uid:0 gid:0 rdev:21,3 O_RDWR | O_NOCTTY name://dev/pts/3 1: S_IFCHR mode:00 dev:10,4 ino:4463 uid:0 gid:0 rdev:21,3 O_RDWR | O_NOCTTY name://dev/pts/3 2: S_IFCHR mode:00 dev:10,4 ino:4463 uid:0 gid:0 rdev:21,3 O_RDWR | O_NOCTTY name://dev/pts/3 5: S_IFREG mode:0555 dev:10,9 ino:139342 uid:0 gid:0 rdev:0,0 O_RDONLY size:194980846 name:/opt/splunkforwarder/bin/splunkd 10: S_IFREG mode:0444 dev:10,5 ino:124151 uid:0 gid:0 rdev:0,0 O_RDONLY size:5875 name:/usr/lib/nls/msg/EN_US/ksh.cat 63: S_IFREG mode:0600 dev:10,4 ino:41933 uid:0 gid:0 rdev:0,0 O_RDWR | O_APPEND size:5494 name://root/.sh_history #
Note: The special variable $$ is replaced by the shell with the shell’s PID.
For file descriptor 5, the absolute path /opt/splunkforwarder/bin/splunkd is displayed.
The file descriptor should of course be closed again:
# exec 5<&- #