Linux篇:Bash配置文件

3,623 阅读6分钟

Bash在启动(以及退出)的时候会自动执行一些文件的内容,这些文件称为Bash的配置文件。Bash的配置文件一般用于:改变Bash的默认行为、设置环境变量、改变终端的交互方式、添加别名或者函数、添加自启动命令。

在介绍Bash的配置文件前,需要先了解一些基本概念。

Shell启动类型

登录Shell与非登录Shell

当用户登录Linux,操作系统会自动给用户分配一个Shell,这个Shell就是登录Shell。

我们在终端输入bash命令启动的Shell,以及执行脚本时根据shebang启动的Shell都属于非登录Shell。

简而言之,我们登录系统的第一个Shell是登录Shell,后面启动的Shell都是非登录Shell。但是,可以使用--login选项强制成为登录Shell。

登录Shell退出时会显示“logout”,而非登录Shell显示“exit”。

交互Shell与非交互Shell

我们登录系统获得的Shell与输入bash命令启动的Shell,都会等待我们输入命令,并把输出内容显示在屏幕上,这就是交互Shell。交互Shell一般都有命令提示符,比如[user@host ~]$

如果我们调用Shell执行一个脚本,就不会等待我们输入命令,也不会出现命令提示符,并且在脚本执行完毕后自动退出,这就是非交互Shell。可以使用-i选项成为交互Shell,但Shell行为不会改变,仍然是非交互的。

交互Shell的$-变量包含字母i,而非交互Shell不包含。

配置文件

不同启动类型的Bash读取不同的的配置文件。

登录Shell

当Bash以登录Shell启动的时候,会首先读取并执行文件“/etc/profile”中的命令。

接着,Bash会依次查找文件“~/.bash_profile”,“~/.bash_login”,“~/.profile”,读取并执行找到的第一个文件中的命令。也就是说,如果“~/.bash_profile”存在,就不会执行“~/.bash_login”和“~/.profile”中的命令。

当交互登录Shell退出,或者非交互登录Shell执行exit命令后,Bash会读取并执行文件“~/.bash_logout”中的命令。当然,执行命令在真正退出前。

交互非登录Shell

当Bash以交互非登录Shell启动时,会读取并执行文件“~/.bashrc”中的命令。一些发行版比如Debian系和Arch Linux系,会先读取并执行文件“/etc/bash.bashrc”的命令,但这不属于Bash规范。

非交互Shell

当Bash以非交互Shell启动时,会读取环境变量“BASH_ENV”,如果变量的值是一个文件,则读取并执行这个文件中的命令。查找这个文件时不会使用“PATH”路径。

配置方法

一般而言,在一个用户进程树中只会有一个登录Shell,它会在其他所有Shell启动之前。所以登录Shell的配置文件适合放一些只需执行一次或者可以被继承的命令。一般登录Shell的配置文件用于:设置umask设置环境变量添加自启动程序

不建议修改“/etc/profile”文件,任何自定义配置都应该在用户空间修改。

/etc/profile”一般都会查找并执行目录“/etc/profile.d”中的文件,如果有软件需要添加登录Shell配置,则应该在“/etc/profile.d”目录下创建配置文件。

此外,一些软件并不按照Bash规范读取配置文件,比如Gnome在用户空间只读取“~/.profile”,而不是按照之前提到的顺序。使用这些软件的时候要注意修改配置文件。


我们手动打开的Bash基本是非登录的,同时也是交互式的。我们在图形界面打开的多个终端模拟器,或者嵌套的每一层交互子Shell,都会读取并执行交互非登录Shell的配置文件。“~/.bashrc”中的配置主要跟用户交互有关,比如设置命令提示符设置终端颜色。此外,由于每一层子Shell都会执行该配置文件中的内容,“~/.bashrc”中的命令应该是不能被继承的,且是每个交互Shell必需的。

别名函数都不能被子Shell继承,所以很适合作为“~/.bashrc”的配置内容。

应该注意到,交互非登录Shell仅有用户空间下的配置文件,而没有“/etc”目录下的配置文件。系统管理员不应该干涉用户的交互方式。

如果确实需要所有用户遵循一些统一的交互规范,可以创建“/etc/bashrc”配置文件,并在用户的“~/.bashrc”文件中加入下面的命令。

[ -f /etc/bashrc ] && source /etc/bashrc

其中source也可以简写为.

同时我们也注意到,登录Shell是不会读取“~/.bashrc”的,但我们需要登录Shell也有这些好用的交互方式。一般我们会在“~/.bash_profile”(或者其他两个用户空间下的登录Shell配置文件)中加入下面的命令来读取交互配置文件。

[ -f ~/.bashrc ] && source ~/.bashrc

登录Shell退出时的配置文件也只有用户空间下的“~/.bash_logout”,如果需要对所有用户生效,可以参考“~/.bashrc”的做法。


我们一般不会去创建非交互Shell的配置文件。对于非交互Shell,有以下两点非常重要。

  • 非交互Shell会继承父Shell的环境变量,所以在执行脚本的时候如PATH这些环境变量是可以用的。
  • 非交互Shell不会读取“~/.bashrc”,所以在脚本中不能使用别名和函数。

最后,我从Bash官网找到相关内容,作为本文的参考和凭证。在bashman手册也可以找到这部分内容。

6.2 Bash Startup Files
======================

This section describes how Bash executes its startup files. If any of the files exist but cannot be read, Bash reports an error. Tildes are expanded in filenames as described above under Tilde Expansion (*note Tilde Expansion::).

Interactive shells are described in *note Interactive Shells::.

Invoked as an interactive login shell, or with '--login'
........................................................

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.

When an interactive login shell exits, or a non-interactive login shell executes the 'exit' builtin command, Bash reads and executes commands from the file '~/.bash_logout', if it exists.

Invoked as an interactive non-login shell
.........................................

When an interactive shell that is not a login shell is started, Bash reads and executes commands from '~/.bashrc', if that file exists. This may be inhibited by using the '--norc' option. The '--rcfile FILE' option will force Bash to read and execute commands from FILE instead of '~/.bashrc'.

So, typically, your '~/.bash_profile' contains the line

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

after (or before) any login-specific initializations.

Invoked non-interactively
.........................

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

but the value of the 'PATH' variable is not used to search for the filename.

As noted above, if a non-interactive shell is invoked with the '--login' option, Bash attempts to read and execute commands from the login shell startup files.