Bash is probably the most common command-line shell in the GNU/Linux world. Although a lot of people use alternate shells (such as Zsh), Bash is still shipped with most mainstream distros as the default. Once you have a lot of different remote machines, all running Bash as the shell, it becomes increasingly difficult to pay attention to the prompt, and typing reboot in a machine different from the one you wanted becomes more likely. I deal with that problem by changing Bash prompts…
First of all, the basics: Bash prompts are just environment variables with special characters you can set and export. Bash has four of these variables: PS1 to PS4, but usually only the first two matters (actually, just PS1 – for a reference on the others, check the manpage). The most common PS1 string is:
spectra@home:~$ echo $PS1
\u@\h:\w\$
spectra@home:~$
This has 4 special characters, escaped with a backslash: \u informing us the username; \h informing us the hostname; \w, informing us the working directory; and \$, which gives us the $ in the end of the prompt (more on this later).
So, essentially, one can change that string to anything else…
spectra@home:~$ PS1="my_shell_prompt\$ "
my_shell_prompt$
Pretty easy. You can check a complete reference of the special characters at the section PROMPTING of bash manpage, but the most useful IMHO are the following:
- \d the date
- \t the time (24-hour format)
- \W the basename of the current working directory
- \! the history number of this command
- \# the command number of this command
- \$ shows # if the UID is 0 (is we are root), or $ for all the rest
Also, as part of the prompt string, one can use ANSI Colors enclosed as non-printing characters (that is between \[ and \]). ANSI sequences always begin with an “ESC[” and end with an “m”. (Yes… Really arbitrary… but that’s the way it is…). ESC can be represented as \e… Here is a list of the most common colors in ANSI sequences:
- Black: 0;30
- Red: 0;31
- Green: 0;32
- Brown: 0;33
- Blue: 0;34
- Purple: 0;35
- Cyan: 0;36
- Light Gray: 0;37
Now, notice that there are two numbers separated by a semi-colon… the first is always 0 (zero) in the colors I pointed above, but it actually refers to an ANSI attribute called Select Graphic Rendition… You can use 0 (zero) to normal colors, 1 for bold, 2 to faint, etc. So \e[0;30m refers to BLACK, \e[1;30m refers to DARK GREY. The Wikipedia has a good article on these escape sequences.
Once you’re satisfied with something printed in a color, to go back to the default (to reset), you issue the \e[0m escape sequence.
So, back to my problem… Each different machine gets a different color for the hostname. On “hospital” machine, for instance, my PS1 looks like:
spectra@hospital:~$ PS1="\[\e[1;33m\]\u\[\e[0m\]@\[\e[0;35m\]\h\[\e[0m\]:\[\e[0;32m\]\w\[\e[0m\]\$ "
spectra@hospital:~$
With \e[0;35m (Purple) for the hostname. On “home” machine, it may be \e[0;34m (Blue)... On “server”, it may be \e[0;36m (Cyan), and so on… After a while, you get used to the color and end up linking the color to the machine… so that typing “reboot” on a machine with the wrong color gets harder than before.
To make the changes permanent, put export PS1 in one of the config script of bash (.bashrc, .bash_profile, etc). On some systems, /etc/environment holds lots of environment variables definitions.
I just scratched the surface… That’s just what works for me… The Bash-Prompt-HOWTO has some interesting examples, and I actually have a friend who uses more esoterical stuff, such as fancybash or bashish, but I’ll leave this up to you…


I really would like to have a bashrc where the hostname is displayed in a color based on a hash of itself, a la most IRC clients. This could be used in a bash_profile that’s shared across a network for places that do NFS homes, etc.
Including the literal string $? in $PS1 allows you to see the return code of your previous process. I find that this encourages me to think actively about the state of the processes i run, which in turn is really useful as i translate my everyday shell use into automated scripts.
If you don’t have it set in $PS1 yet, but you want to try it out temporarily, just do:That will prefix your prompt with the return code of the most recent command. (Make sure you use single-quotes around it to protect $? from getting interpreted by the shell during the variable assignment itself, instead of at prompt generation time.)
Whoops! i expected code elements to be inline-styled, and pre elements to be block-styled, and there was no preview option. Sorry about the poorly-formatted comment above! Feel free to edit the code elements to tt (or whatever makes it readable).
Good article, Pablo. I have had similar problems in the past, e.g. shutting down the wrong machine, and came to the same conclusion.
I have a script called bashprompt that I have evolved, which is placed in /etc and handles my prompts. The nice thing about it is that you only need to place an echo ”. /etc/bashprompt” in each users’ .bashrc (and /etc/skel/.bashrc)
@Daniel,
I also expected it to be that way… :-) For now I just changed to italics, but I definitively have to fix that.
Hi Pablo,
A good tool to avoid rebooting the wrong server is Martin Krafft’s excellent package: http://packages.debian.org/sid/molly-guard
It hooks into the reboot/shutdow commands and asks you to type the hostname of the box you want to reboot (if it’s not the local machine).
Francois
That’s rather useless, I’d say.
Best protection against typing “reboot” on wrong system?
Limit the time you work as root. Plain and simple. And it actually helps in a lot of other situations.
P.S. As to shell prompt coloring, Here is my PS1 made after idea picked on Slashdot.
PS1=’\T [\h:\w]\[`test ”$?” -ne “0” && echo -ne ”\e[31m”`\]\$\[`echo -ne ”\e[0m”`\] ‘
The $/# would change color to red if last command return code wasn’t 0.
@Dummy0001,
As I said, that’s just what works for me… maybe I have some rather good color recognization stream of thought :-)
As for limiting the time spent as root… sure, that’s a good advice.