How can I programmatically get the PID of the active GNOME Terminal instance?

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

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

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