Knowing that program's PID, I want to list out the executable file of a running program.

For binary programs, I can read /proc/$pid/exe, which is a symlink to the executable.

However for scripting programs, for example a Python program, /proc/$pid/exe points to /usr/bin/python, not the program itself. This happens no matter I started the program with ./program.py or with python program.py.

I tried several ways to solve it:

/proc/$pid/cmdline contains the filename of the script, but it is in relative path and the working directory may have changed already.

I also tried /proc/$pid/comm but it can be easily changed by the program.

So how to know the original script file of a running program?

  • 1
    echo 'puts "what script file?"' | ruby -
    – thrig
    Apr 6 '16 at 18:27
  • ps -ef | grep "$pid" should give you the full command for the process including what script is being run and what options were given. But the output is dependent on what is running and how it was called. Don't know if this will answer your question so posting as comment.
    – Munir
    Apr 6 '16 at 18:32
  • @Munir ps -ef is the same as /proc/$pid/comm. The problem is the filename is relative path, not absolute path. Apr 6 '16 at 18:35
  • @StarBrilliant They are not the same...Example - I have tuned running on my RHEL server as PID 16865. ps -ef gives me /usr/bin/python /usr/sbin/tuned -d -c /etc/tuned.conf but cat /proc/16865/comm just says tuned.
    – Munir
    Apr 6 '16 at 18:42
  • @Munir It's my typo. I meant /proc/$pid/cmdline. It's cmdline instead of comm. Apr 7 '16 at 12:35

Can we assume the files are not changed on disk (at least, no files with the same name added or deleted) and /proc/[pid]/cmdline is reliable (see side note below)?

According to proc(5): /proc/[pid]/environ contains the initial environment variables (which won't be changed even if the program itself changes the envrionment variables inside) including PWD and PATH.

if the path in cmdline starts with relative dirname(s), you can use PWD (in /proc/[pid]/environ) as the base path and resolve the relative path;
if the path in cmdline is the name of the program itself, you can loop through each directory in PATH (in /proc/[pid]/environ) and the target is the first file with the same name.

Side notes:

/proc/[pid]/exe seems to be the dereferenced file (e.g. /usr/bin/python3.6 instead of /usr/bin/python3 or /usr/bin/python if they are symlinks);

/proc/[pid]/cmdline can also contain strange information for some programs so may be unreliable. This seems to be related to the program but not the kernel, and I didn't observe any python scripts behaving this way (and editing sys.argv in python doesn't seem to affect /proc/[pid]/cmdline). My question also talked a bit about this.


Experimentally, for bash, /proc/{pid}/fd/255 is a link to the full path of the executed script.

#! /bin/bash

ls -l /proc/$$/fd/255
  • Because any shell has to process a script line-by-line, the shell process will always have an open handle to the file it reads the script from: in bash it's 255, in dash it's 10, in zsh and ksh it's 11, in yash it's 100, etc. But that's NOT the case in perl or python, which are compiling the whole script at once, and closing the file it was read from before running it.
    – user414777
    Jan 25 at 21:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.