15

Is there a way to make the bash prompt dynamic, so that it changes color when logged into a server?

So I want the like the color to be green when on my system and change to red when connected to servers. I have huge number of servers I don't want to put a different .bashrc on all those.

9

The remote prompt is set by the remote ~/.bashrc. So you still need to copy it to the remote server. However, you can use a single ~/.bashrc for all hosts, and set the prompt color based on hostname:

[ "$PS1" ] || return 0                           # continue only when interactive
case $(hostname -s) in
laptop*)
    prompt_color='\033[48;5;16m\033[38;5;46m'    # green(46) on black(16)
    ;;
server*)
    prompt_color='\033[48;5;16m\033[38;5;196m'   # red(196) on black(16)
    ;;
esac
ORIG_PS1=$PS1                                    # in case needed
PS1='<\['${prompt_color}'\]\h\[\033[m\]:\w>\$ '
unset prompt_color

Notes:

  • Don't set PS1 if it's not already set (i.e., if the shell is not interactive). Testing if PS1 is non-empty is a very common way to decide if the shell is interactive, and you don't want to confuse programs that do that. (Arguably a more accurate test is checking if $- contains i.)

  • If you want this code to run when logging into a remote server, you should have one of the profile files always source ~/.bashrc. But I assume you know that.

  • In PS1, the escape codes must be enclosed in \[...\].

  • \[033[m resets foreground and background to default. So here, :\w appear in terminal foreground/background.

  • \[033[48;5;XXXm\033[38;5;YYYm sets the background/foreground to XXX/YYY.

  • For a script that dumps the available colors, try colortest.

  • To check what the prompt would look like:

    echo -e "<\033[48;5;16m\033[38;5;196mhost\033[m:dir>$ "
    
| improve this answer | |
7

If you don't want to (can't) make the remotes have a separate PS1, then I'd say "no", it would be at least awfully difficult. Consider that on an SSH connection the local side has no real idea of what is a shell prompt and what is something else, and so setting colors for the prompt really has to come from the remote. You could set colors before starting the session, but they'd be effective for all output, that is until an ls or an editor sets colors of it's own.

Of course you could come up with some wrapper for the session to detect everything looking like a prompt and to colorize it, but it would easily lead to false positives (color on every line with a $?) and be awfully complicated compared to just dropping a single line to your .profile or .bashrc on each machine.

With a number of machines, it might be useful in any case to search for solutions to synchronize configuration changes on all of them. Be it some tool made for it, or just a script, or just running a loop to copy a (set of) config file(s) on them all.

| improve this answer | |
  • 2
    That last paragraph is the key. If OP is administering "a huge number of servers" it's astonishing that each one has to be configured individually in the first place. – Lightness Races in Orbit Aug 29 '16 at 10:39
5

I am using a wrapper script with sshpass that will first upload a temporary profile and then ssh using this profile (and delete the temp file).

The two main things of the script are these:
scp ~/.bash_remote "${USER}"@"${IP}":/tmp/.bash_tmp 1>/dev/null
ssh -t "${USER}"@"${IP}" "bash --rcfile /tmp/.bash_tmp; rm /tmp/.bash_tmp"

Using this you can easily define the colors of the remote sessions.

I know this doesn't directly answer your question, but it could be used to solve it.

| improve this answer | |
  • 3
    Don't use sshpass -p if at all possible! Command line arguments to running programs are usually visible to all users in ps, and so will be the password. Even if you have no other user accounts on the machine, you might print it on the screen accidentally. sshpass can read the password from an environment variable, which isn't too hard to use. Also, consider ssh keys if you're going to save the login credentials to a file anyway. – ilkkachu Aug 29 '16 at 7:22
  • You are right and I wasn't trying to promote the use of it. I was just pasting as an example from my script which is only being used for development purpose and provides no security risk. The SSHPASS variable will be left empty for production systems where ssh keys are used. I will update. – Mikael Kjær Aug 29 '16 at 7:34
1

You might be interested in context-color, which I've put together for that exact purpose: https://github.com/ramnes/context-color

It's a simple script that, when executed, outputs a color based on a command output's hash. With it installed somewhere in your $PATH, you could do something like this in your .bashrc:

export PS1="$(context-color -p)$PS1\[\e[0m\]"

(where --prompt/-p is the switch so that the color is escaped for prompts, and \[\e[0m\] the escape sequence to reset color)

By default, the command used to generate the hash is whoami; hostname. If you just want the color to change according to the hostname, you can change the $CONTEXT variable environment (export CONTEXT="hostname") or simply use the --context/-c option (context-color -c "hostname").

See below for an example:

demo

| improve this answer | |

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.