LINUX实战:Bash启动时加载配置文件过程
《LINUX实战:Bash启动时加载配置文件过程》要点: 本文目次: 1.1 断定是否交互式、是否登录式 1.2 几种常见的bash启动方式 1.3 加载bash情况配置文件 当用户登录系统时,会加载各种bash配置文件,还会设置或清空一系列变量,有时还会执行一些自界说的命令.这些行为都算是启动bash时的过程. 另外,有些时候登录系统是可以交互的(如正常登录系统),有些时候是无交互的(如执行一个剧本),因此总的来说bash启动类型可分为交互式shell和非交互式shell.更细分一层,交互式shell还分为交互式的登录shell和交互式非登录shell,非交互的shell在某些时候可以在bash命令后带上"--login"或短选项"-l",这时也算是登录式,即非交互的登录式shell. 1.1 判断是否交互式、是否登录式判断是否为交互式shell有两种简单的办法: 办法一:判断变量"-",如果值中含有字母"i",表示交互式. [root@linuxidc~]# echo $- himBH [root@linuxidc~]# vim a.sh #!/bin/bash echo $- [root@linuxidc~]# bash a.sh hB 办法二:判断变量PS1,如果值非空,则为交互式,否则为非交互式,因为非交互式会清空该变量. [root@linuxidc~]# echo $PS1 [u@h W]$ 判断是否为登录式的办法也很简单,只需执行"shopt login"即可.值为"on"表示为登录式,否则为非登录式. [root@linuxidc~]# shopt login_shell
login_shell on
[root@linuxidc~]# bash [root@linuxidc~]# shopt login_shell login_shell off 所以,要断定是交互式以及登录式的情况,可简单使用如下命令: echo $PS1;shopt login_shell ? 1.2 几种常见的bash启动方式(1).正常登录(伪终端登录如ssh登录,或虚拟终端登录)时,为交互式登录shell. [root@linuxidc~]# echo $PS1;shopt login_shell [u@h W]$ login_shell on (2).su敕令,不带"--login"时为交互式、非登录式shell,带有"--login"时,为交互式、登录式shell. [root@linuxidc~]# su root [root@linuxidc~]# echo $PS1;shopt login_shell [u@h W]$ login_shell off [root@linuxidc~]# su - Last login: Sat Aug 19 13:24:11 CST 2017 on pts/0 [root@linuxidc~]# echo $PS1;shopt login_shell [u@h W]$ login_shell on (3).执行不带"--login"选项的bash敕令时为交互式、非登录式shell.但指定"--login"时,为交互式、登录式shell. [root@linuxidc~]# bash [root@linuxidc~]# echo $PS1;shopt login_shell [u@h W]$ login_shell off [root@linuxidc~]# bash -l [root@linuxidc~]# echo $PS1;shopt login_shell [u@h W]$ login_shell on (4).使用命令组合(使用括号包抄命令列表)以及命令替换进入子shell时,继承父shell的交互和登录属性. [root@linuxidc~]# (echo $BASH_SUBSHELL;echo $PS1;shopt login_shell) 1 [u@h W]$ login_shell on [root@linuxidc~]# su [root@linuxidc~]# (echo $BASH_SUBSHELL;echo $PS1;shopt login_shell) 1 [u@h W]$ login_shell off (5).ssh执行长途命令,但不登录时,为非交互、非登录式. [root@linuxidc~]# ssh localhost 'echo $PS1;shopt login_shell' login_shell off (6).执行shell剧本时,为非交互、非登录式shell.但指定了"--login"时,将为非交互、登录式shell. 例如,剧本内容如下: [root@linuxidc~]# vim b.sh #!/bin/bash echo $PS1 shopt login_shell 不带"--login"选项时,为非交互、非登录式shell. [root@linuxidc~]# bash b.sh login_shell off 带"--login"选项时,为非交互、登录式shell. [root@linuxidc~]# bash -l b.sh login_shell on (7).在图形界面下打开终端时,为交互式、非登录式shell. ? 但可以设置为使用交互式、登录式shell. ? ? 1.3 加载bash环境配置文件无论是否交互、是否登录,bash总要配置其运行环境.bash环境配置主要通过加载bash环境配置文件来完成.但是否交互、是否登录将会影响加载哪些配置文件,除了交互、登录属性,有些特殊的属性也会影响读取配置文件的办法. bash环境配置文件主要有/etc/profile、~/.bash_profile、~/.bashrc、/etc/bashrc和/etc/profile.d/*.sh,为了测试各种情形读取哪些配置文件,先分别向这几个配置文件中写入几个echo语句,用以断定该配置文件是否在启动bash时被读取加载了. echo "echo '/etc/profile goes'" >>/etc/_profile
echo "echo '~/.bash_profile goes'" >>~/.bash_profile
echo "echo '~/.bashrc goes'" >>~/.bashrc
echo "echo '/etc/bashrc goes'" >>/etc/bashrc
echo "echo '/etc/profile.d/test.sh goes'" >>/etc/profile.d/test.sh
chmod +x /etc/profile.d/test.sh
①.交互式登录shell或非交互式但带有"--login"(或短选项"-l",例如在shell剧本中指定"#!/bin/bash -l"时)的bash启动时,将先读取/etc/profile,再依次搜索~/.bash_profile、~/.bash_login和~/.profile,并仅加载第一个搜索到且可读的文件.当退出时,将执行~/.bash_logout中的命令. 但要注意,在/etc/profile中有一条加载/etc/profile.d/*.sh的语句,它会使用source加载/etc/profile.d/下所有可执行的sh后缀的剧本. [root@linuxidc~]# grep -A 8 *.sh /etc/profile for i in /etc/profile.d/*.sh ; do if [ -r "$i" ]; then if [ "${-#*i}" != "$-" ]; then . "$i" else . "$i" >/dev/null 2>&1 fi fi done 内层if语句中的【"${-#*i}" != "$-"】表现将"$-"从左向右模式匹配"*i"并将匹配到的内容删除(即进行变量切分),如果"$-"切分后的值不等于"$-",则意味着是交互式shell,于是怎样怎样,否则怎样怎样. 同样的,在~/.bash_profile中也一样有加载~/.bashrc的敕令. [root@linuxidc~]# grep -A 1 ~/.bashrc ~/.bash_profile if [ -f ~/.bashrc ]; then . ~/.bashrc fi 而~/.bashrc中又有加载/etc/bashrc的敕令. [root@linuxidc~]# grep -A 1 /etc/bashrc ~/.bashrc if [ -f /etc/bashrc ]; then . /etc/bashrc fi 其实/etc/bashrc中还有加载/etc/profile.d/*.sh的语句,但前提是非登录式shell时才会执行.以下是部门语句: if ! shopt -q login_shell ; then # We're not a login shell
...
for i in /etc/profile.d/*.sh; do
if [ -r "$i" ]; then
if [ "$PS1" ]; then
. "$i"
else
. "$i" >/dev/null 2>&1
fi
fi
done
...
fi
从内层if语句和/etc/profile中对应的判断语句的作用是一致的,只不外判断方式不同,写法不同. 因此,交互式的登录shell加载bash环境配置文件的实际进程如下图: ? 以下成果验证了结论: Last login: Mon Aug 14 04:49:29 2017 # 新开终端登录时
/etc/profile.d/*.sh goes
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes
[root@linuxidc~]# ssh localhost # ssh远程登录时 root@localhost's password: Last login: Mon Aug 14 05:05:50 2017 from 172.16.10.1 /etc/profile.d/*.sh goes /etc/profile goes /etc/bashrc goes ~/.bashrc goes ~/.bash_profile goes [root@linuxidc~]# bash -l # 执行带有"--login"选项的login时 /etc/profile.d/*.sh goes /etc/profile goes /etc/bashrc goes ~/.bashrc goes ~/.bash_profile goes [root@linuxidc~]# su - # su带上"--login"时 /etc/profile.d/*.sh goes /etc/profile goes /etc/bashrc goes ~/.bashrc goes ~/.bash_profile goes [root@linuxidc~]# vim a.sh # 执行shell脚本时带有"--login"时 #!/bin/bash -l echo haha [root@linuxidc~]# ./a.sh /etc/profile goes /etc/bashrc goes ~/.bashrc goes ~/.bash_profile goes haha 之所以执行shell脚本时没有显示执行/etc/profile.d/*.sh,是因为它是非交互式的,根据/etc/profile中的【if [ "${-#*i}" != "$-" ]】判断,它将会把/etc/profile.d/*.sh的执行结果重定向到/dev/null中.也便是说,即使是shell脚本(带"--login "选项),它也加载了所有bash环境配置文件. ②.交互式非登录shell的bash启动时,将读取~/.bashrc,不会读取/etc/profile和~/.bash_profile、~/.bash_login和~/.profile. 因此,交互式非登录shell加载bash环境配置文件的实际进程为下图内方框中所示: 例如,执行不带"--login"的bash敕令或su敕令时. [root@linuxidc~]# bash /etc/profile.d/*.sh goes /etc/bashrc goes ~/.bashrc goes [root@linuxidc~]# su /etc/profile.d/*.sh goes /etc/bashrc goes ~/.bashrc goes ③.非交互式、非登录式shell启动bash时,不会加载前面所说的任何bash环境配置文件,但会搜索变量BASH_ENV,如果搜索到了,则加载其所指定的文件.但有并非所有非交互式、非登录式shell启动时都邑如此,见情况④. 它就像是如许的语句: if [ -n "$BASH_ENV" ];then . "$BASH_ENV" fi 几乎执行所有的shell脚本都不会特意带上"--login"选项,因此shell脚本不会加载任何bash情况配置文件,除非手动配置了变量BASH_ENV. ④.远程shell方式启动的bash,它虽然属于非交互、非登录式,但会加载~/.bashrc,所以还会加载/etc/bashrc,由于是非登录式,所以最终还会加载/etc/profile.d/*.sh,只不外因为是非交互式而使得执行的结果全部重定向到了/dev/null中. 如果了解rsync,就知道它有一种远程shell连接方式.所谓的远程shell方式,是指通过网络的方式启动bash并将bash的尺度输出关联起来,就像它连接了一个远程的shell守护进程一样.一般由sshd实现这样的连接方式,老版的rshd也一样支持. 事实也确实如此,使用ssh连接但不登录远程主机时(例如只为了执行远程命令),便是远程shell的方式,但它却是非交互、非登录式的shell. [root@linuxidc~]# ssh localhost echo haha root@localhost's password: /etc/bashrc goes ~/.bashrc goes haha 正如上文所说,它同样加载了/etc/profile.d/*.sh,只不外/etc/bashrc中的if判断语句【if [ "$PS1" ]; then】使得非交互式的shell要将执行结果重定向到/dev/null中. 本文永远更新链接地址: 《LINUX实战:Bash启动时加载配置文件过程》是否对您有启发,欢迎查看更多与《LINUX实战:Bash启动时加载配置文件过程》相关教程,学精学透。编程之家PHP学院为您提供精彩教程。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |