.bashrc不起作用与bash初始化文件执行顺序

.bashrc不起作用

按习惯在HOME中添加了.bashrc文件,定义一些alias和PS1,结果发现putty登录之后并未生效,还须手动source .bashrc,在~/目录增加.bash_profile或.profile解决:

 ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.

# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
        . "$HOME/.bashrc"
    fi
fi

# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
    PATH="$HOME/bin:$PATH"
fi

但问题的根源在于.bash_profile .bashrc .bash_login .profile几个文件的执行顺序。

.bash_profile .bashrc .bash_login .profile执行顺序

bash startup文件执行顺序

man是个好东西,man bash:

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

可见这些文件的执行顺序如下:

  • /etc/profile
  • ~/.bash_profile
  • ~/.bash_login
  • ~/.profile

但同时需要注意前提条件是bash是interactive login shell,那什么是interactive shell,什么是login shell?

interactive shell和login shell

A login shell is one whose first character of argument zero is a -, or one started with the --login option.

An interactive shell is one started without non-option arguments (unless -s is specified) and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option. PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.

上面的定义虽然字字都能看懂,但按字面理解起来比较困难。通俗地来说,interactive shell就是需要人机交互的,比如执行一个脚本就不需要人机交互。login shell就是是否需要登录,比如本地再开一个terminal就不需要再次登录。

参考如下实例对二者排列组合: # Differentiate Interactive login and non-interactive non-login shell

  • interactive login shell: 远程登录,如ssh
  • interactive non-login shell: 本地起一个bash
  • non-interactive non-login shell: 运行脚本
  • non-interactive login shell: 少见

可以用如下命令测试当前环境是什么样的bash:

~$: echo $-; shopt login_shell
himBHs
login_shell     on
第一行中如果含有字母i则是iteractive shell;第二行显而易见。上述执行结果是ssh,可见ssh是iteractive login shell。

.bashrc又在什么时候被调用?

When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist.

好了,因为putty通过ssh登录,因此它是iteractive login shell,所以不会调用.bashrc,因此开头增加.bash_profile或.profile文件的目的就是调用.bashrc。

Tips: Linux中有许多不同版本的shell,如sh、csh、tcsh、zsh等。它们之间有一定的继承和渊源,有兴趣可以了解一下。只不过bash在当前的发行版中最为常见。