在 Linux 环境,服务器启动 / 使用各种 ssh 工具 (e.g. putty) 开启新的 session 登录时,系统会加载启动文件导入环境变量等。本文就是探讨启动文件的加载顺序。
启动文件
有两种类型的启动文件
全局文件:适用于所有登录服务器的用户。一般在/etc
目录下。比如:
/etc/profiles
/etc/bashrc
/etc/bash.bashrc
这些,一般都是需要 root 操作权限的。
用户文件:适用于某个用户。一般在用户自己的根目录下:~/
, /home/username/
。比如:
.profiles
.bash_profile
.bashrc
.bash_login
这些,一般使用该用户账户登录即拥有所有操作权限。
以上这些启动文件,不一定每个都存在。但是如果存在多个的情况下,加载那个,先后顺序,有的时候尤为重要。
Shell 类型
Shell 有三种类型。下面一一介绍。因为不同类型的 Shell ,启动文件加载顺序不一样。
Interactive Login Shell
交互式登录 Shell ,比如ssh
,putty
,xterm
,需要输一遍用户名密码登录的。(有的软件会存用户名密码,第二次登录就不需要输入了,但也属于这个类别。)
Interactive non-login Shell
交互式非登录 Shell,当你已经登录了这个 server ,再使用 bash
或者 zsh
开启一个新的 Shell 窗口,就不需要登录了。
Non-interactive Shell
非交互式 Shell,这个一般指 shell script 脚本,且非以#!/bin/bash
开头。
顺序
参考网上总结的一张图,顺序如下:
按照 A->B->C 的顺序,如果同一类别有多个的话(如B1,B2,B3)就取第一个 available 的。
- 总结1:先加载系统文件,后加载用户文件
- 总结2:交互式登录的,一般先看
~/.bash_profile
,再看~/.profile
Why it matters
简而言之:需要保证各个文件之间的兼容性。
最常见的一个 case , dev 使用 putty 登录上 server 后,即开启了一个Interactive Login Shell
。然后跑了一个脚本(以#!/bin/bash
开头),即开启了一个Interactive non-login Shell
。这时,假设按顺序 load 了以下几个文件:
/etc/profile
~/.profile
~/.bashrc
需要保证,最后 load 的 ~/.bashrc
不会 "无意间地" 把前面定义好的环境变量覆写掉。
最佳实践思考
1.不要定义那么多不同的启动文件,尽可能只使用少量的1-2个文件,比如~/.profile
,~/.bashrc
。
2.灵活地在脚本中使用source
。
3.对于只适用于 interactive mode 的,可以考虑加上[ -z "$PS1" ] && return
判断条件。
参考
- Bash Startup Files Loading Order https://youngstone89.medium.com/unix-introduction-bash-startup-files-loading-order-562543ac12e9
- Understanding Shell Initialization Files and User Profiles in Linux https://www.tecmint.com/understanding-shell-initialization-files-and-user-profiles-linux/
- StackOverFlow Question https://stackoverflow.com/questions/18186929/what-are-the-differences-between-a-login-shell-and-interactive-shell