How to detect the number of opened terminals by the user

6,983

Solution 1

If you really need to get the number of terminal you have open, go for counting the files owned by you under /dev/pts (although this might include ones opened by background processes, not by graphical terminal emulators). Alternatively, count the number of child processes of your terminal emulator(s), as shown by Jacob in the first line of his response.

Avoid relying on who's output, and looking for gnome-pty-helper processes, since these don't work in newer gnome-terminal versions.

Note that nowadays pretty much all graphical terminal emulators (including putty) and multiplexers (screen, tmux) support 256 colors. You can get really nice colored prompts if you use this palette.

My recommendation for a very simple solution is to base the color on the current tty line's number. E.g. process the output of the tty command to take the number only and derive the color from that. A certain tty line number is only given to one terminal at a time, you'd have to close that terminal first before the same line number is reissued by the kernel. This, combined with 256 colors, automatically guarantees that you won't see the same color twice at a given time (and even with 16 colors it'd give a quite even distribution). No need for maintaining a global counter, and no need for counting terminals or processes.

Solution 2

In a single user situation, if we take the example of xterm, we can simply count the number of pids of xterm; xterm creates a separate pid for each and every window.
gnome-terminal however runs a single pid, but the good news is that it creates a child process for each and every window and/or tab. we can retrieve these child processes by the command:

pgrep -P <pid_of_gnome-terminal>

There are however a few complications to deal with:

  • Reading your question, we may assume, that user in this case is actually owner of the x-session. Usually we can simply use the $USER -variable, but this might not match the currently logged in user of $DISPLAY.

  • In a multi-user situation, pids belonging to the (either which) terminal application, do not necessarily belong to the current $DISPLAY. We need to split off only the relevant pids and child-pids.

  • On Unity (15.10 or lower), if a second user logs in, an additional process is started (gnome-pty-helper), which appears as a child process in gnome-terminal, but the process (obviously) has no window or tab. On Mate, the process exists anyway.

In short

To count the number of tabs and/or windows of a terminal application, we need to:

  • See if we run a terminal application which has multiple pids or a single pid on one $DISPLAY (x-session)
  • From the running processes, split off only the relevant pids, running on this $DISPLAY
  • If the application runs child-processes for its pid (for windows/tabs), see if gnome-pty-helper runs, to correct the number.

This can very well be scripted however, to reliably find the number of currently opened windows and/or tabs.

The script

In the script below, the targeted terminal application is used as an argument. The script works on many terminals I tested it on. An exception is Tilda at this moment.

An example

  • I have two users logged in, one (not the current) with two gnome-terminal windows, one (the one in the image) with three gnome-terminal windows, and two xterm windows.

enter image description here

The command:

/path/to/get_terms.sh gnome-terminal

outputs:

3

while

/path/to/get_terms.sh xterm

outputs:

2

The script

#!/bin/bash

terminal=$1

# get the user running the current x-session
username=$(who | grep $DISPLAY | head -1 | awk '{print $1}')
# get the pid of the terminal for the current user
userpid=$(pgrep -u $username $terminal)
# check what type the terminal is (multi pid/single pid)
npids="$(echo "$userpid" | wc -w)"
# in case of a single pid, count the children
if [ "$npids" -eq 1 ]; then
  # check if gnome-pty-helper runs (starts when multiple users are logged in)
  ptpid=$(pgrep gnome-pty-helpe)
  # get number of child- procs
  let "orig = $( pgrep -P $(pgrep -u $username $terminal) | wc -w )" 
  # if pty-helper runs, correct the number of child procs
  if [ -n "$ptpid" ] && [ -n "$userpid" ]; then
    let "n_terms = $orig-1"; else let "n_terms = $orig"
  fi
  # if no child procs run, n-terminals = n-counted pids (difference Mate <> Unity)
  if [ "$n_terms" -eq 0 ]; then echo $orig; else echo $n_terms; fi
# in case of multiple pids, count the pids
elif [ "$npids" -gt 1 ]; then echo $npids
fi

To use

  • Copy the script into an empty file, save it as get_terms.sh, make it executable and run it by the command:

    /path/to/get_terms.sh <terminal_application>
    

Solution 3

An awk way:

who | awk 'BEGIN{count=0}{ if(NR!=1){count++} }END{print count}'

Explanation:

In above 1 liner command, awk is used to find the count of terminal. Inside awk program, it is just checking the number of lines return by who command - 1.

Share:
6,983

Related videos on Youtube

manav m-n
Author by

manav m-n

Please note that this profile is outdated and kept here only for historical reasons. Name: Unknown Location: Unknown Education: Unknown Facebook/Twitter/Instagram: None

Updated on September 18, 2022

Comments

  • manav m-n
    manav m-n over 1 year

    I am using Ubuntu and can manually change the bash shell prompt color to green using

    export PS1="\e[0;32m[\u@\h \W]\$ \e[m" 
    

    However, I want the shell prompt color to automatically change whenever I open a new terminal or tab. I am aware that the basic tty TERM has 16 colors, and it's okay to rotate the colors if more than 16 terminals are open. Will the solution also work when I connect through Putty, tmux or screen.

    My idea is to write a shell script and place it in .bashrc which detects the new terminal session the user has opened and increment a global counter from \e[0;31m[ to \e[0;47m[. How to detect the number of opened terminals by the user?

  • GreggD
    GreggD almost 8 years
    This one works very nice for my mate-terminal & xterm, seems bullet-proof.
  • GreggD
    GreggD almost 8 years
    Beautiful idea with tty. I guess we/others have concentrated too much on that "question" and forgot that there might be other solutions for entire "need" :) I would even play with implementing random color selector. If it's 256 colors, selecting same/similar colors should not happen much. However manually setting colors for given pts numbers will give better personalization.
  • egmont
    egmont almost 8 years
    @TedM. Yes the question was pretty much phrased as an XY question, along the lines of: "I wish to have different color in each terminal, so tell me: how do I count the number of terminals?"
  • egmont
    egmont almost 8 years
    @TedM. Random is also a nice idea! (One property of a deterministic mapping is that after sudoing the new user might easily set the same prompt color. This may or may not what the original asker wants to have.)
  • GreggD
    GreggD almost 8 years
    Randomizer is quite easy: color="\e[38;5;"$(((RANDOM % 231 )+1))"m" (only 231 to reject greyscale), however many of those colors happened to be just different shades and couple of those are dark so might be almost invisible and I guees nobody will use that in real life...
  • GreggD
    GreggD almost 8 years
    Right here I always have one gnome-pty-helper running, even when there's only one user logged-in (right after reboot) and when I open any amount of terminals it runs second, same helper. Your new script seems to be working for mate-terminal (wasn't able to cause that zero-thing), but with xterm, when I have only 1 opened it shows 0 and starts showing good number only after second one and with gnome-terminal it always shows one too less (outputing 0 when only one is opened).
  • egmont
    egmont almost 8 years
    We don't know the asker's Ubuntu version. In 16.04 there is definitely no gnome-pty-helper anymore (git.gnome.org/browse/vte/commit/?id=299c700). I'm not going to downgrade to check the exact process hierarchy in older versions. I know there used to be such process, I'm just not entirely sure how the parent-child hierarchy looked like. By the way, I took the child-process-count idea from your original response, so I don't understand that "(also by you)", nevermind.
  • Jacob Vlijm
    Jacob Vlijm almost 8 years
    @TedM. Thanks, that is useful information, fixed now.
  • GreggD
    GreggD almost 8 years
    I really admire your "passion" :) ... but there's still a problem with gnome-terminal. One gives 1, two gives 1, three gives 2, four gives 3, etc.. Plus my new discovery, MATE's "Tilda" (that one extra "unknown" terminal in my answer) also have same issue as gnome-terminal, but with it's tabs. xterm and mate-terminal seems to be working fine though.
  • Jacob Vlijm
    Jacob Vlijm almost 8 years
    @TedM. Thanks for mentioning! Silly question, but are you sure you use the latest code? On Mate 15.10 all test I run work without exception. What is your Mate version? On Unity everything already worked fine.
  • Jacob Vlijm
    Jacob Vlijm almost 8 years
    @TedM. Also on my pretty blank 15.10 Mate, it is there by default. Just re- ran the tests, perfectly! could I ask you tomorrow or so to run an edited version of the script and post the output somewhere, to see what causes the exception in your case?
  • Jacob Vlijm
    Jacob Vlijm almost 8 years
  • muru
    muru almost 8 years
    Concisely: who | awk 'END{print NR - 1}', since what you want is number of lines - 1.
  • Jacob Vlijm
    Jacob Vlijm almost 8 years
    Since OP wants to use the outcome to automatically set the terminal color(s), this seems not a really relevant option.
  • NonStandardModel
    NonStandardModel almost 8 years
    Sorry I see now he wants to use it in script. But then would ps -ef | grep UserName | grep bash | grep -v grep | wc -l not work?
  • manav m-n
    manav m-n almost 8 years
    @egmont: may you also explain why who output is unreliable