最近在ubuntu系统中做一个关于程序开机自启动的问题
由于环境变量在不同的运行模式下读取的流程不一样,导致在服务器开机重启后运行既定程序找不到相应的环境变量错误
这里做一篇博客来探讨一下环境变量的读取过程
首先,要明确几个概念,登录型shell和非登录型shell,交互型shell(interactive shell) 和非交互型shell(non-interactive shell)
登录型shell:简单来说, 就是在终端输入用户名和密码后得到的shell
非登录型shell:简单来说,就是在图形界面或者文字界面键入(strl+alt+t)或者Bash命令得到的一个新窗口
交互型shell:简单来说,就是需要用户在图形或者文本界面下需要键入命令和shell进行交互
非交互型shell:简单来说,就是执行一个sh脚本,eg:bash example.sh
首先,声明一点的是ubuntu 16.04系统家目录下(~目录),与环境变量相关的文件只有.bashrc .bash_logout .profile
在系统目录下有两个文件:/etc/profile和/etc/bash.bashrc
首先在/etc/profile文件里:export a='/etc/profile'
同样的,在/etc/bash.bashrc文件中设置export a='/etc/bash.bashrc'
同样的,在~/.profile文件中设置export a='/home/mllabs/.profile',因为普通用户是mllabs
同样的,在~/.bashrc文件中设置export a='/home/mllabs/.bashrc'
准备工作就绪,下面登录账户mllabs
在shell界面echo $a:
从该图可以看出,文本模式登录,读取的环境变量文件是:/etc/profile->/etc/bash.bashrc->~/.profile->~/.bashrc
在普通用户模式下,键入su命令,进入root用户,然后echo $a
可以看到,在上一步的基础上重新读取了/etc/bash.bashrc文件和root用户自身的~/.bashrc文件
在root用户环境下,键入su - mllabs -c 'echo $a'
可以看到,只读取了/etc/profile文件和~/.profile两个文件,说明su - user命令相当登录型非交互式shell
在root用户环境下,键入su - mllabs -c 'source /home/mllabs/.bashrc && echo $a'
输出的还是:
为什么source /home/mllabs/.bashrc 命令会失效呢,一开始百思不得其解
后来在查看~/.bashrc文件内容中发现,这样一条命令
case $- in
*i*) ;;
*) return ;;
esac
这一段代码是判断当前shell是否为交互型shell,所以就算手动执行source /home/mllabs/.bashrc,也不能将.bashrc文件中的环境变量读取到。
再谈bash example.sh
在这里我新建了一个测试脚本
#test.sh
#!/bin/bash
echo $a
在这个脚本中输出变量a的值
同时,在终端也输出a的值
可以发现a的值是没有 变化的,这就说明bash test.sh命令是新建一个子进程,这个子进程是完全继承当前的父进程,并不属于交互型shell,所以并没有触发环境变量的读取