使用服务器部署软件,有时候需要自己编译,当编译安装完成后,我们需要设置环境变量,为了方便快捷的运行命令,而不必每次都使用绝对路径。
问题描述:
服务器安装完JDK环境后,习惯的在/etc/profile.d目录下写一个声明环境变量的脚本,比如:
export JAVA_HOME=/usr/local/javaexport PATH=$JAVA_HOME/bin:$PATH
需要使用命令:source /etc/profile.d/java.sh 使其生效。
偶尔的一次重启服务器之后,发现环境变量未生效,需要手动source 执行/etc/profile.d脚本使其生效。
问题排查:
- 系统开机会执行/etc/profile脚本,脚本执行过程中,会for循环遍历/etc/profile.d目录下的.sh文件并执行。
- 用户登录时,会执行/etc/bashrc脚本,脚本执行过程中,也会for循环遍历/etc/profile.d目录下的.sh文件并执行。
- 代码:
for i in /etc/profile.d/*.sh; do if [ -r "$i" ]; then if [ "$PS1" ]; then . "$i" else . "$i" >/dev/null fi fi done
问题解决过程:
- 首先检查/etc/profile.d目录下声明环境变量的脚本是否可读
- /etc/profile 系统开机时运行的脚本,发现此脚本里声明了很多全局变量,但是用户登录后,全部没有生效,说明此脚本中声明的PATH被后执行的脚本中的PATH覆盖了。
- ~/.bash_profile 用户登录后执行的脚本,脚本里有一个条件判断语句,如果~/.bashrc文件存在则执行~/.bashrc,然后再声明PATH变量。
![9cb42b5b2dddcb83766bc7b721773b87.png](https://i-blog.csdnimg.cn/blog_migrate/cbd40715e31e4c855b5244bf5814273a.jpeg)
- ~/.bashrc 此脚本也有一条判断语句,如果/etc/bashrc存在,则执行/etc/bashrc
![3269c7fc558fb10046d74bb970ca069b.png](https://i-blog.csdnimg.cn/blog_migrate/c3dd2be8c3304309eeb73ff2b2f9bdff.jpeg)
- /etc/bashrc 查看此脚本时,发现脚本的最后一行声明了PATH全局变量,这里的PATH把之前声明的PATH全部覆盖了。
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/git/bin
总结:
删除/etc/bashrc里的PATH声明,并整理/etc/profile里的环境变量的声明,一并移到/etc/profile.d目录下,而且官方也是建议这么做的,好处就是好管理,不会破坏系统脚本里的东西。
由此可以分析出,这4个脚本的执行顺序是:
开机执行/etc/profile,用户登陆shell后,执行~/.bash_profile,执行~/.bash_profile的过程中,会先执行~/.bashrc,执行~/.bashrc的过程中,会执行/etc/bashrc