8

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?

7

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.

  • 1
    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. – GreggD May 20 '16 at 20:15
  • @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 May 20 '16 at 20:20
  • @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.) – egmont May 20 '16 at 20:25
  • 1
    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 May 20 '16 at 20:42
  • 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. – egmont May 20 '16 at 21:27
5

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>
    
  • 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). – GreggD May 20 '16 at 21:23
  • @TedM. Thanks, that is useful information, fixed now. – Jacob Vlijm May 21 '16 at 5:21
  • 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. – GreggD May 21 '16 at 20:18
  • @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 May 21 '16 at 20:30
  • @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 May 21 '16 at 20:36
1

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.

  • this returns 0 for me, which is clearly untrue... – Zanna May 20 '16 at 6:37
  • This one works very nice for my mate-terminal & xterm, seems bullet-proof. – GreggD May 20 '16 at 6:56
  • Concisely: who | awk 'END{print NR - 1}', since what you want is number of lines - 1. – muru May 22 '16 at 17:12
0

Simple way may be also just to run System Monitor (if started from Terminal you must write gnome-system-monitor) and under "Processes" tab arrange the running processes by Name and than count the number of occurrences of Bash in the listing (they will be all together if you arrange by name, so it's easy to count).

Note that you must look for Bash and not for Gnome Terminal if you want to see the number of opened terminals by user. Once you open a Terminal Gnome Terminal will also appear in the Processes list but will remain only one even if more Terminals are opened. The "View" button in System Monitor allows you to set which processes to see, eg. All Processes/User Processes/Active ...

  • Since OP wants to use the outcome to automatically set the terminal color(s), this seems not a really relevant option. – Jacob Vlijm May 27 '16 at 21:07
  • 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? – NonStandardModel May 27 '16 at 21:34

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

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