1. Configuration
-
Create a /etc/skel/.bash_aliases file.
cat << 'EOF' | sed 's/^ //' | sudo tee /etc/skel/.bash_aliases > /dev/null
# Set default editor.
export EDITOR=vim
export VISUAL=vim
# Do not put duplicate lines or lines starting with space in history.
export HISTCONTROL=ignoreboth
# Expand aliases in shell scripts and inside vim when using the :! command.
shopt -s expand_aliases
# Append to history file, do not overwrite it.
shopt -s histappend
# Set history length.
export HISTSIZE=10000
export HISTFILESIZE=20000
export NCURSES_NO_UTF8_ACS=1
# Disable <Ctrl-d> to prevent accidental log out.
set -o ignoreeof
# Don't echo control characters.
if `tty -s`; then
stty -echoctl
fi
# Show user and hostname in green, show working directory in blue.
# The "\[\e]0;\u@\h\a\]" string is used to change the PuTTY window title.
# It will also get rid of the annoying "Thanks for flying Vim" title.
PS1='\[\e]0;\u@\h\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
# Alias definitions.
if [ -f ~/.bashrc_aliases ]; then
. ~/.bashrc_aliases
fi
EOF
-
Create a /etc/skel/.bashrc_aliases file.
cat << 'EOF' | sed 's/^ //' | sudo tee /etc/skel/.bashrc_aliases > /dev/null # A trailing space in the alias value causes the next word to be checked # for alias substitution when the alias is expanded. E.g. "sudo dir /". alias sudo='sudo ' # Several aliases for list command. alias vdir='ls --color=auto --show-control-chars -l' alias dir='ls --color=auto --show-control-chars' alias ls='ls --color=auto --show-control-chars' alias ll='ls --color=auto --show-control-chars -l' alias l='ls --color=auto --show-control-chars -lA' # Alias for hexadecimal dump. alias hex='od -t x1' # Aliases for "diff" that ignore case and white space. alias diff-c='diff --color' alias diff-i='diff -i' alias diff-w='diff -w' alias diff-iw='diff -i -w' # Aliases for "git diff" that ignore case and white space. alias git-diff="git difftool -x '/usr/bin/diff' -y" alias git-diff-c="git difftool -x '/usr/bin/diff --color' -y" alias git-diff-i="git difftool -x '/usr/bin/diff -i' -y" alias git-diff-w="git difftool -x '/usr/bin/diff -w' -y" alias git-diff-iw="git difftool -x '/usr/bin/diff -iw' -y" # Some aliases to prevent making mistakes. alias cp='cp -i' alias mv='mv -i' alias rm='rm -i' EOF
There is no need to back up the original .bashrc files, because the original ~delta/.bashrc file was copied from /etc/skel/.bashrc and the original ~root/.bashrc file was copied from /usr/share/base-files/dot.bashrc.
# Copy skeleton files to user accounts. sudo /bin/cp -a /etc/skel/.bash_aliases ~delta sudo /bin/cp -a /etc/skel/.bashrc ~delta sudo /bin/cp -a /etc/skel/.bashrc_aliases ~delta sudo chown delta:delta ~delta/.bash_aliases sudo chown delta:delta ~delta/.bashrc sudo chown delta:delta ~delta/.bashrc_aliases sudo /bin/cp -a /etc/skel/.bash_aliases ~root sudo /bin/cp -a /etc/skel/.bashrc ~root sudo /bin/cp -a /etc/skel/.bashrc_aliases ~root # Change color of root prompt from green to red. sudo sed -i 's/green/red/' ~root/.bash_aliases sudo sed -i 's/;32m/;31m/' ~root/.bash_aliases
2. Information
2.1. Check for interactive shell
Enter the following command at a Command Line.
[[ $- == *i* ]] && echo "Interactive" || echo "Non-interactive"
2.2. Check for login shell
Enter the following command at a Command Line.
shopt -q login_shell && echo "Login shell" || echo "Non-login shell"
There is an another way of detecting you are in a login shell. The login process tells the shell to behave as a login shell with the following convention: passing argument 0, which is normally the name of the shell executable, with a - character prepended (e.g. -bash whereas it would normally be bash). You can use the echo $0 command to return argument 0.
When the first character returned by the echo $0 command is a dash or hyphen you are in a login shell. Thus, when echo $0 returns -bash then you are in a login shell. However, when it returns bash you may or may not be in a login shell. This is because when invoking an interactive login shell with the bash --login command, the echo $0 command returns bash instead of -bash.
2.3. The BASH_ENV variable
When Bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute. Bash behaves as if the following command were executed.
if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
2.4. Interactive login shell
An interactive login shell is invoked when you log in on a text console, or through bash --login, or ssh, or su -, or tmux.
[[ $- == *i* ]] && echo "Interactive" || echo "Non-interactive" shopt -q login_shell && echo "Login shell" || echo "Non-login shell"
bash --login [[ $- == *i* ]] && echo "Interactive" || echo "Non-interactive" shopt -q login_shell && echo "Login shell" || echo "Non-login shell" exit
On Debian GNU/Linux the following files are sourced when Bash is invoked for an interactive login shell.
/etc/profile /etc/bash.bashrc /etc/profile.d/*.sh ~/.profile ~/.bashrc
2.5. Interactive non-login shell
An interactive non-login shell is invoked when you start another shell through bash, or dash.
bash [[ $- == *i* ]] && echo "Interactive" || echo "Non-interactive" shopt -q login_shell && echo "Login shell" || echo "Non-login shell" exit
On Debian GNU/Linux the following files are sourced when Bash is invoked for an interactive non-login shell.
/etc/bash.bashrc ~/.bashrc
Note that the /etc/profile, /etc/profile.d/*.sh and ~/.profile files are not sourced.
2.6. Non-interactive login shell
A non-interactive login shell is invoked for example through echo '<command>' | ssh localhost, or bash --login -c.
touch ~/.hushlogin echo '[[ $- == *i* ]] && echo "Interactive" || echo "Non-interactive"' | ssh localhost echo 'shopt -q login_shell && echo "Login shell" || echo "Non-login shell"' | ssh localhost /bin/rm ~/.hushlogin
bash --login -c '[[ $- == *i* ]] && echo "Interactive" || echo "Non-interactive"' bash --login -c 'shopt -q login_shell && echo "Login shell" || echo "Non-login shell"'
On Debian GNU/Linux the following files are sourced when Bash is invoked for a non-interactive login shell.
/etc/profile /etc/profile.d/*.sh ~/.profile ~/.bashrc "$BASH_ENV"
Note that the /etc/bash.bashrc file is not sourced.
2.7. Non-interactive non-login shell
A non-interactive non-login shell is invoked for example through ssh localhost '<command>', or bash -c, or a cron job.
ssh localhost '[[ $- == *i* ]] && echo "Interactive" || echo "Non-interactive"' ssh localhost 'shopt -q login_shell && echo "Login shell" || echo "Non-login shell"'
bash -c '[[ $- == *i* ]] && echo "Interactive" || echo "Non-interactive"' bash -c 'shopt -q login_shell && echo "Login shell" || echo "Non-login shell"'
On Debian GNU/Linux the following files are sourced when Bash is invoked for a non-interactive non-login shell.
"$BASH_ENV"
2.8. Packages
The various Bash startup files are provided by the bash and base-files packages.
dpkg -L base-files | grep -i '\/etc' | grep -E 'bash|prof|skel'
/etc/profile.d /etc/skel
dpkg -L bash | grep -i '\/etc' | grep -E 'bash|prof|skel'
/etc/bash.bashrc /etc/skel/.bash_logout /etc/skel/.bashrc /etc/skel/.profile
~root/.bashrc is copied from /usr/share/base-files/dot.bashrc. ~root/.profile is copied from /usr/share/base-files/dot.profile.
dpkg -L bash | grep -i 'bashrc' dpkg -L bash | grep -i 'profile' dpkg -L base-files | grep -i 'bashrc' dpkg -L base-files | grep -i 'profile'
2.9. Summary
| Startup file | Interactive login | Interactive non-login | Non-interactive login | Non-interactive non-login |
|---|---|---|---|---|
/etc/profile |
Yes |
- |
Yes |
- |
/etc/bash.bashrc |
Yes |
Yes |
- |
- |
/etc/profile.d/*.sh |
Yes |
- |
Yes |
- |
~/.profile |
Yes |
- |
Yes |
- |
~/.bashrc |
Yes |
Yes |
Yes, but skipped |
- |
BASH_ENV |
- |
- |
Yes |
Yes |
There is no proper way to add system wide custom settings without an update of the bash or base-files package overwriting your custom settings. The only way is to use the ~/.bash_aliases file that is sourced in the ~/.bashrc file.
3. Scripting
3.1. Block Comments
Disable Block of Code Using Here Document
In a shell script, one way to disable a block of code is to prefix every line of the code with a '#' to make them into comments. However, we can do it much more efficiently using heredoc with the dummy command ':'. For example, we can disable several lines of code in our shell script:
#!/bin/bash # disable-with-heredoc.sh : <<'DISABLED' echo "This line will not show up in the console. echo "Neither will this line. DISABLED echo "This line will be printed to the console
By turning a block of code into a heredoc and redirecting it to the dummy command ':', we’ve essentially prevented the block of code from executing. We’ve enclosed the delimiter token to escape all the special characters in the content. This is done to prevent any command substitution from being executed, thereby preventing any unintended side effects.