Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I understand that it may be a rare situation for an executable to have spaces in it, but it could happen.

An example may be the best explanation..

Using standard tools, I want to determine the location (on the file system) of the executable which owns(?) the current window...

  1. get the current window ID ...(xdotool getactivewindow )
  2. use the ID to get the PID ...(wmctrl -p -l | sed ... ID ....
  3. use the PID to get the executable's name ... (ps -A ... here is where I run into problems !

Whith ps, when listing only the executable's name (-o ucmd), it truncates the name to 15 characters, so this rules out this option for any name which is longer.
Widening the column (-o ucmd:99 ) makes no difference.. If pgrep is anything to go by, its matching is limited to 15 because of stat (see: info pgrep)..

Listings in variants of "full" mode (eg -A w w) are not useful when the name concerned has spaces in it, because this name is separated from its args by another space!.. Also, in "full" mode, if the process was started by a link, the name of the link is shown, rather than the executable's name.

Is there some way to do this (using standard tools)? ...or are spaces a show stopper here?

share|improve this question
    
I am not sure this can be classified as standard: cat "/proc/$PID/cmdline" |cut -d "" -f1 –  João Pinto Jan 15 '11 at 11:46
    
It's looking very interesting, but nautilus has bogged down while trying to load 58,000 files in /proc (Is that normal to have that many there; what are they all doing?)... and I believe ti is absolutely standard... It is as standard as passing data from an email cliendt to a Word Processor, then including some pics you tweaked in a picture tweaker, adding an audio clip you prepared, and a spreadsheet thrown in.. Acatually I prefer the simple stuff like ls and grep.... :) GUI stuff is too complicated ... –  Peter.O Jan 15 '11 at 12:37
    
This gives me what I'm after readlink -e /proc/$PID/exe.. the executable's full path... but I don't know enough about proc (yet) to know if this works consistantly... Also as is the case with a with good answer as a comment; it leave the question "hanging".. so João, could you adapt this comment to an answer.. I like it.. it is as simple as ls ... no spreadsheet formulas(ae?) to deal with.. :) –  Peter.O Jan 15 '11 at 12:59
    
(ammended comment) /proc/$PID/cmdline does extract the name with any spaces includes, and when that name is a link, then readlink -e "$(cat "/proc/9577/cmdline"|cut -d "" -f1)" tracks down the exe... (and it's good to know you an cut at a null :) –  Peter.O Jan 15 '11 at 13:43
    
NB... For anyone reading this, please note that the cut method does not work with null (it appears to work... see more detailed comments in the comment section of Gilles answer.... –  Peter.O Jan 16 '11 at 4:33

2 Answers 2

up vote 7 down vote accepted

All utilities get their information from /proc/$PID anyway, but there are (at least) three places in /proc/$PID that contain the name of the executable in some form, and they report different information.

  • The Name field in /proc/$PID/status (also available in a harder-to-parse form in /proc/$PID/stat). This is the name of the executable, but truncated to 15 characters. Since the kernel performs the truncation, no option to ps can help. That's what ps -o comm (or its synonym ps -o ucmd) shows.
  • The symbolic link /proc/$PID/exename point to the executable file. You can get its contents with readlink /proc/$PID/exename. Unlike the information reported by ps, only the user running the process has permission to read the link target.
  • The zeroth argument to the process, as chosen by the shell or other program that invoked it. By convention, shells choose the name of the executable as you typed it (with or without a full path). You can get all the arguments from ps with ps -o cmd (or its synonym ps -o command), but the arguments are separated by spaces so you can't reliably tell where the zeroth argument stops. You can read the arguments from /proc/cmdline, where they are separated by null character: </proc/$PID/cmdline awk -vRS='\0' '{print; exit;}' extracts the zeroth argument.

For completeness, let me mention that these names can change during the lifetime of the process, though most programs don't do it:

  • The process can change Name field of /proc/$PID/status by calling prctl with the PR_SET_NAME argument.
  • The executable file can be renamed or deleted. In simple cases, Linux keeps track of the new name (but edge cases might not work, e.g. if you make a hard link to the executable). If the file is deleted, the kernel adds (deleted) to the link target.
  • The zeroth argument to the process is read from process memory (it's argv[0] in C). The process can modify it freely.
share|improve this answer
1  
This explanation works better than my solution. Try: which "$(readlink /proc/$(xdotool getwindowpid $(xdotool getactivewindow))/exe)" –  zpletan Jan 15 '11 at 17:59
    
@fred.bear: Thanks for spotting this. Both tr commands are meant to swap newlines with nulls. head extracts the first line; the whole tr/head/tr pipe extracts the first null-terminated chunk. In this particular case, the second tr command could be tr '\0' '\n' since there's a single chunk left. –  Gilles Jan 15 '11 at 18:30
    
@Gilles.. Thanks! another mystery unwravelled... very well explained.... (btw.. It seems the typo gremlim struck again...the first tr args should be \\0 \\n)... and thanks for the bonus insight: ..obfiscate the trailing newline by nulling it out... (I'm not sure how bash handles nulls.. I suppose I can use '-d \\n' until I have a fuller understanding) .... and another bonus (by example)... not using 'cat' when '<' does the job... I read someone's blog tirrade about that ,and such things, the other day (by a Randal Schwartz (perhaps the one from 'FLOSS Weekly'...:) –  Peter.O Jan 15 '11 at 18:32
    
Just for the record :), because I need it as a var, I'm going with: cmd="$(</proc/10773/cmdline cut -d '' -f1)" ... –  Peter.O Jan 15 '11 at 18:58
1  
@fred.bear: cut alone won't work in the rare case when the string to extract contains a newline. –  Gilles Jan 15 '11 at 19:24
ps $PID | tail -1 | awk '{i=5; while (i<NF) {printf "%s ", $i; i++}; print $NF}'

Where $PID is the PID you have. Probably the full command you want (based on your question above) is:

which "$(ps $(xdotool getwindowpid $(xdotool getactivewindow)) | tail -1 | awk '{i=5; while (i<NF) {printf "%s ", $i; i++}; print $NF}')"
share|improve this answer
    
.. Up to a certain point, your solution works. However my question relates to beyond that point... ie. when the command has 3 specific attributes... (1) The basename is longer than 15... (2) It has embedded spaces... (3) There are Args... eg. In /usr/bin make a link: 'Link to gedit with spaces'... Run this link with the Arg 'test file'... Then get its PID... Then the command portion of ps $PID returns this: /usr/bin/Link to gedit with spaces test file ... As you can see this ps output is not parsable.. Where do the Args begin? ... –  Peter.O Jan 15 '11 at 17:37
    
Yeah, I understand now. Sorry! See my comment on Gilles's solution below. –  zpletan Jan 15 '11 at 18:00
    
I finally got around to testing your suggestion (in Gille's comment).. Again, it works, but only up to a point; a different point this time... As Gille's mentions in his 2nd point (about /proc/$PID/exe). "only the user running the process has permission to read the link target." ... The 3rd method he mentions, is however accessible.... eg. I, as a "user", cannot access a roo owned target of "../exe", but I can access a root owned "../cmdline"... (It certainly has been an interesting little journey. ;) PS Thanks for pointing out xdotools getwindowpid.. I'd missed that one completely~ –  Peter.O Jan 16 '11 at 4:21
    
Hmmm. That's true, I suppose. I had assumed (bad thing to do!) that you would own the active window; I guess there are cases (e.g. Synaptic) where that's not the case. Sorry. –  zpletan Jan 16 '11 at 13:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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