Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How can I get the PID of the GNOME Terminal instance I'm using from within a Bash script?

I can run xprop _NET_WM_PID and then manually click the terminal window, but I'd like to completely automate this.

share|improve this question
up vote 3 down vote accepted

I've written two recursive functions that trace parents of a process

get_parent()
{
 ps --no-headers -p $1 -o ppid,cmd 
}

process_list()
{
  if [ "$1" -ne "1"  ]; then
   PARENT="$(get_parent $1 )"
   printf "%s\n" "$PARENT"
   process_list $( printf "%s" "$PARENT" | awk '{print $1}'  )
  fi 
}

print_header()
{
  printf "PPID\tPROCESS\n"
  for i in $(seq 1 20 ) 
  do
     printf "-"
  done
  printf "\n"
}
print_header
process_list $$

What I've found in the process is this:

$ bash get_process_list                                                        
PPID    PROCESS
--------------------
31264 bash get_process_list
31251 mksh
16696 gnome-terminal
15565 /bin/mksh
 2164 x-terminal-emulator
 1677 init --user
 1342 lightdm --session-child 12 19
    1 lightdm

So we could use the two functions and grep the gnome-terminal, assuming that's what the user wants. If the user wants any terminal emulator, that may be problematic because aside from checking lsof for a pts device open, there's no way to tell whether or not the process is a terminal emulator.

Aside from that , there is something very interesting as well:

$ bash get_process_list                                                                    
PPID    PROCESS
--------------------
32360 bash get_process_list
23728 -mksh
 2164 tmux
 1677 init --user
 1342 lightdm --session-child 12 19
    1 lightdm

tmux apparently forks itself and the process gets picked up by init , so again there's the obstacle.

Using Unity's Ayatana

The code bellow uses qdbus and Ayatana's dbus interface to list all gnome-terminal windows and whether they are focused at the moment or not. This can be later parsed or edited to output only active/focused window PID

Sample run:

$ bash get_gt_pd.sh                                                                    
XID:33554486    PID:20163   ACTIVE:true
XID:33554444    PID:20163   ACTIVE:false

And the code itself

get_gt_xid()
{ # Prints XID of each gnome-terminal window
 qdbus --literal org.ayatana.bamf \
      /org/ayatana/bamf/matcher \
     org.ayatana.bamf.matcher.XidsForApplication \
    /usr/share/applications/gnome-terminal.desktop
}

for window in  $(get_gt_xid | awk -F'{' '{ gsub(/\,|}|]/," ");print $2  }' )
do
  PID=$(qdbus org.ayatana.bamf /org/ayatana/bamf/window/"$window"\
        org.ayatana.bamf.window.GetPid)
  ACTIVE=$( qdbus org.ayatana.bamf /org/ayatana/bamf/window/"$window"\
            org.ayatana.bamf.view.IsActive  )
  printf "XID:%s\tPID:%s\tACTIVE:%s\n" "$window" "$PID" "$ACTIVE"
done
share|improve this answer
    
This returns the PID of my tmux instance. – ændrük Apr 6 at 21:27
    
That wasn't mentioned in the question :) Of course if you have tmux run the script , the parent PID will be of tmux . What's your complete setup ? – Serg Apr 6 at 21:36
    
Arbitrary—the answer should avoid making assumptions about my setup, where practical. – ændrük Apr 7 at 20:41
    
@ændrük well , what sort of assumtions can we make ? can we at least assume that script will be run through gnome-terminal at all times ? Because if your ultimate goal is determining whether or not a script is being run over which terminal emulator, then it will be very difficult to determine - there's tons of terminal emulators, and searching for every possible string that is name of a terminal will be a bit difficult. To the os, terminal emulator is nothing but another process , distinguished from others only by pid – Serg Apr 7 at 23:05
    
I shouldn't have distracted you by mentioning tmux. Consider instead that if I had used this answer from within a script I would have initially responded with "this returns the PID of my Bash instance." – ændrük Apr 7 at 23:14

There are times when more than one instance is running — when I have a terminal open in a guest session, for example

The variable $PPID will give you the parent process for the current bash shell, which is often gnome-terminal.

To be safe though, the following will find the parent gnome-terminal process even if multiple bash shells are nested:

pstree -p -s $PPID | grep -Po 'gnome-terminal\(\K.*?(?=\))'


The following universal version will work for any shell, even if other grep instances are running. Deciphering it is left as an exercise for the reader ;)

pstree -p -a -s \
$(pstree -p -a | grep -B3 $RANDOM$RANDOM \
| grep -m1 `echo $SHELL |cut -d/ -f3` | cut -d, -f2)\
| grep gnome-terminal | cut -d, -f2
share|improve this answer
    
True, but I think any method that assumes there is only one GNOME Terminal instance is still fundamentally flawed. Another counterexample: gnome-terminal --disable-factory – ændrük May 20 '12 at 1:02
    
See edited answer ;) – izx May 20 '12 at 2:28

This solution feels the most robust to me. It recursively looks up the parent PID until finding one that belongs to GNOME Terminal.

find-parent() {
    i=($(ps -o pid= -o ppid= -o cmd= -p $1))
    ((i[0] == 1)) && return 1
    if [[ ${i[2]} =~ (^|/)gnome-terminal$ ]]; then echo ${i[0]}; else find-parent ${i[1]}; fi
}; find-parent $PPID
share|improve this answer

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.