I am writing a python application, which uses Popen to start other exectutables. I then use Psutil to collect information about them.
One of the things I need is the exact CMD I used to start the application. For example:
>>> p = psutil.Popen(
['/path/to/binary', 'arg1', 'arg2'],
env=env,
cwd=cwd,
start_new_session=True,
)
I then need psutil to show me ['/pat/to/binary', 'arg1', 'arg2']
. Note that I need to be able to get this line across main app restarts, so I cannot just save the command I used in a variable in my app. Only other option to do that is to write it to file, which is what I would like to avoid.
However, it looks like the kernel is changing the proctitle because:
>>> p.cmdline()
['ld-linux-x86-64.so.2', '--argv0', '/path/to/binary', '--preload', '/lib/libgcompat.so.0 ', '--', '/path/to/binary', 'arg1', 'arg2']
If I manually read /proc/339/cmdline
I also get the same thing, so it is not a problem with psutil.
And it looks like ld-linux-x86-64.so.2
is not int PATH so I cannot just execute this CMD to run the executable.
I can obviously parse this and just take whatever comes after --
but that would work only in this particular case and will break when a process cmdline is normal (without the ld-linux-x86-64.so.2 ...
stuff) and contains --
in its arguments list.
Is there a way to get just the command and args I used originally without having to save the command I used to a file?
Looks like I would have to answer my own question. I wished there was a better way to do this but looks like there isn't.
The workaround I ended up doing assumes that the cmdline list ends with the arguments of the executable, preceded by the absolute executable path (which I know). So I use this to extract it from the rest:
>>> cmdline = p.cmdline()
>>> cmdline
['ld-linux-x86-64.so.2', '--argv0', '/path/to/binary', '--preload', '/lib/libgcompat.so.0 ', '--', '/path/to/binary', 'arg1', 'arg2']
>>> cmdline.reverse()
>>> first_arg_index = len(cmdline) - cmdline.index("/path/to/binary")
>>> cmdline.reverse()
>>> cmdline[first_arg_index:]
['arg1', 'arg2']
This should also work for normal cmdlines i.e. /path/to/binary arg1 arg2
, but will break if the dynamic linker changes the way it starts the executable.