docker-stacks icon indicating copy to clipboard operation
docker-stacks copied to clipboard

Colorize terminal through /etc/bash.bashrc as /home/jovyan/.bashrc tends to be wiped

Open consideRatio opened this issue 6 years ago • 8 comments

It is my understand that if we would not override /home/jovyan we probably would end up with a default .bashrc copied from /etc/skel/.bashrc, but that this is wiped in general due to mounting of storage in /home/jovyan.

Perhaps we could try to retain it somehow, for example by doing...

# Add systemwide .bashrc configuration additions that are normally found in /home/jovyan/.bashrc
USER root
RUN cat /etc/skel/.bashrc >> /etc/bash.bashrc
USER $NB_UID

Resulting changes from unmodified /etc/skel/.bashrc usage

  1. (not true, it requires force_color_prompt=yes is un-commented!) We get colors on the prompt, like...

image

  1. We get colors on the ls commands output

  2. (untested) We get a custom title that isn't Terminal 1 Terminal 2 etc on the terminal tabs, but instead the username and hostname and the path following that... It comes from the following section of the .bashrc and the first part of the PS1 variable. It is too messy though...

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

Resulting changes from modifying the /etc/skel/.bashrc before using

Assuming we do the following on the /etc/skel/.bashrc before we utilize it by for example augmenting /etc/bash.bashrc, we end up with a result that I consider pleasing.

  • remove /h from PS1
  • remove "\u@\h: " from the xterm title section
  • remove comment from force_color_prompt=yes

beautify-terminal


/etc/skel/.bashrc from Ubuntu 18.04

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
    xterm-color|*-256color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
	# We have color support; assume it's compliant with Ecma-48
	# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
	# a case would tend to support setf rather than setaf.)
	color_prompt=yes
    else
	color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

# Add an "alert" alias for long running commands.  Use like so:
#   sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
  if [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
  elif [ -f /etc/bash_completion ]; then
    . /etc/bash_completion
  fi
fi

/etc/bash.bashrc from Ubuntu 18.04

# System-wide .bashrc file for interactive bash(1) shells.

# To enable the settings / commands in this file for login shells as well,
# this file has to be sourced in /etc/profile.

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, overwrite the one in /etc/profile)
# but only if not SUDOing and have SUDO_PS1 set; then assume smart user.
if ! [ -n "${SUDO_USER}" -a -n "${SUDO_PS1}" ]; then
  PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi

# Commented out, don't overwrite xterm -T "title" -n "icontitle" by default.
# If this is an xterm set the title to user@host:dir
#case "$TERM" in
#xterm*|rxvt*)
#    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
#    ;;
#*)
#    ;;
#esac

# enable bash completion in interactive shells
#if ! shopt -oq posix; then
#  if [ -f /usr/share/bash-completion/bash_completion ]; then
#    . /usr/share/bash-completion/bash_completion
#  elif [ -f /etc/bash_completion ]; then
#    . /etc/bash_completion
#  fi
#fi

# sudo hint
if [ ! -e "$HOME/.sudo_as_admin_successful" ] && [ ! -e "$HOME/.hushlogin" ] ; then
    case " $(groups) " in *\ admin\ *|*\ sudo\ *)
    if [ -x /usr/bin/sudo ]; then
	cat <<-EOF
	To run a command as administrator (user "root"), use "sudo <command>".
	See "man sudo_root" for details.
	
	EOF
    fi
    esac
fi

# if the command-not-found package is installed, use it
if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then
	function command_not_found_handle {
	        # check because c-n-f could've been removed in the meantime
                if [ -x /usr/lib/command-not-found ]; then
		   /usr/lib/command-not-found -- "$1"
                   return $?
                elif [ -x /usr/share/command-not-found/command-not-found ]; then
		   /usr/share/command-not-found/command-not-found -- "$1"
                   return $?
		else
		   printf "%s: command not found\n" "$1" >&2
		   return 127
		fi
	}
fi

consideRatio avatar Feb 20 '19 09:02 consideRatio

Lots of good info here - I didn't quite follow the wiped/mounted-storage bit, but I suppose it refers to the late-creation of the container runtime user account.

What about something like this - you can make use of the fact that .bashrc looks late for .bash_aliases, and co-opt that somewhat hackishly to set PS1 as you please:

docker run -it --rm jupyter/minimal-notebook bash
# hmmm, no colour prompt

tee > bash_aliases <<"EOF"
export PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
EOF

docker run -it --rm -v $(pwd)/bash_aliases:/home/jovyan/.bash_aliases jupyter/minimal-notebook bash
# colour PS1!

javabrett avatar Feb 22 '19 02:02 javabrett

Adding a file (bash_aliases, bashrc in skel, etc.) at build time to make the prompt prettier sounds good to me. If we copy a custom/etc/skel/.bashrc into the image before adduser in base-notebook, I think it'll get copied properly to that user's home dir. That seems like the right hook to use on the face of it, but I don't have a strong opinion on the implementation.

parente avatar Feb 28 '19 19:02 parente

Customising/simplifying the base-image coloured PS1 prompt aside - is this simply a matter of setting TERM to something that supports colour:

docker run -it --rm --name jupyter -p 8888:8888 -e TERM=xterm-256color jupyter/minimal-notebook

... and when shelling-in to that, I have colour, and

$ echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$

This does not help for the terminal plugin in JupyterLab - something must be clearing it to TERM=xterm, but if TERM=xterm-256color is added near the top of user jovyan .bashrc, subsequent terminal shells will have coloured PS1.

javabrett avatar Mar 06 '19 02:03 javabrett

I opened PR #826 to enable terminal colors for a couple common use cases. It doesn't address customizing the default prompt or colorizing the terminal in all possible cases (e.g., user mounts a home directory not containing a .bashrc), both of which I think would be better served through documentation of specific recipes.

Feedback welcome.

parente avatar Mar 13 '19 01:03 parente

@consideRatio @javabrett (or anyone else) would you like to take another pass at terminal colorization to support the use cases my PR didn't handle or should we close this out?

parente avatar Mar 31 '19 17:03 parente

@parente hmmm sorry for dropping the ball on this and thanks for your work!

I'd love to see a system wide default configuration to allow the users with no .bashrc file get colors as well. For all JupyterHub's where we mount the home folder this will happen for example, and perhaps there is no real drawback to have something system wide configured rather than distributing the configuration to the home directories based on a template in /etc/skel.

I'm not a ninja when it comes to these things, how would we go about this? After reading on this unicorn based webpage I'm thinking that perhaps we should have set things in /etc/profile instead?

So for ~/.bashrc, you could edit the system wide config files /etc/bash.bashrc (for functions/aliases) or /etc/profile (for environment stuff) - you can the full list from man bash:

Oh reading further, this is what I figure we should do, we add a file to /etc/profile.d such as /etc/profile.d/colorize-term.sh.

consideRatio avatar Mar 31 '19 18:03 consideRatio

Porting the lines from /etc/skel/.bashrc that enable terminal and prompt colors to a new scripta in/etc/profile.d may do the trick. The only guidance I can give is to give it a shot and try running container with various settings (e.g., no home mount, a home mount with an .bashrc already present in the host folder, a home mount without a .bashrc, etc.) and see what works and what breaks.

parente avatar Mar 31 '19 18:03 parente

Hello,

Just made some checks on this topic and putting those instructions in /etc/profile.d will not work since most of the shells launched in this context are non-login shells that will not execute the content of /etc/profile.d. I think the the best solution is to move what is currently done in /etc/skel/.bashrc to /etc/bash.bashrc. /etc/bash.bashrc will be executed for all interactive shells (login and not login) before executing the ~/.bashrc. So it can answer to @consideRatio expectations and work as a system wide default configuration for color and other bash stuff.

I can draft something to test if it works as expected 😄

Here are very interesting posts on this topic:

romainx avatar Oct 21 '20 06:10 romainx