shell相关-------各环境变量配置文件及对应的shell模式

■各配置文件

1./etc/profile

系统中每个用户登录时都要执行这个脚本,如果系统管理员希望某个设置对所有用户都生效,可以写在这个文件里

2.~/.bash_profile、~/.bash_login和~/.profile

这些是在当前用户主目录下定义的,其实主要是~/.bash_profile,其他两个一般好像不存在。

[root@localhost sabopeusr0]# ls -a ~
.  ..  .bash_history  .bash_logout  .bash_profile  .bashrc  .cshrc  .tcshrc  anaconda-ks.cfg

~/.bash_profile,如果希望某个设置只对当前用户生效,可以写在这个文件里。

由于这个脚本在/etc/profile之后执行,/etc/profile设置的一些环境变量的值在这个脚本中可以修改,
也就是说,当前用户的设置可以覆盖(Override)系统中全局的设置。

~/.profile这个启动脚本是sh规定的,bash规定首先查找以~/.bash_开头的启动文件,

如果没有则执行~/.profile,是为了和sh保持一致。

3.~/.bash_logout

在退出登录时会执行~/.bash_logout脚本(如果它存在的话)。

4.~/.bashrc

在图形界面下开一个终端窗口,或者在登录Shell提示符下再输入bash命令,就得到一个交互非登录的Shell。
这种Shell在启动时自动执行~/.bashrc文件并以fork子shell的方式执行,即继承父shell的环境变量,并依据.bashrc来修改,
执行完后本地变量不会保存到父shell中去。

[root@localhost sabopeusr0]# ps -ef|grep -v grep|grep bash
sabopeu+  8906  8905  0  7月26 pts/2  00:00:00 -bash
root     11223 11222  0 09:41 pts/2    00:00:00 bash
[root@localhost sabopeusr0]# bash
[root@localhost sabopeusr0]# ps -ef|grep -v grep|grep bash
sabopeu+  8906  8905  0  7月26 pts/2  00:00:00 -bash
root     11223 11222  0 09:41 pts/2    00:00:00 bash
root     11392 11223  0 13:00 pts/2    00:00:00 bash
[root@localhost sabopeusr0]#

有时为了使登录Shell也能自动执行~/.bashrc,通常在~/.bash_profile中调用~/.bashrc:
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
上面的意思是,如果~/.bashrc文件存在则source它。多数Linux发行版在创建帐户时会自动创建~/.bash_profile和~/.bashrc脚本,
~/.bash_profile中通常都有上面这几行。所以,如果要在启动脚本中做某些设置,使它在图形终端窗口和字符终端的Shell中都起作用,
最好就是在~/.bashrc中设置。

■Shell模式

1.交互式登录shell启动

/etc/profile,~/.bash_profile,~/.bash_login和~/.profile

1)以Bash的方式启动登录shell(/etc/passwd里定义的shell是/bin/bash,默认就是这种方式)

/etc/profile⇒~/.bash_profile⇒~/.profile

(~/.profile这个启动脚本是sh规定的,bash规定首先查找以~/.bash_开头的启动文件,如果没有则执行~/.profile,是为了和sh保持一致。)

2)以sh的方式启动登录shell(/etc/passwd里定义的shell是/bin/sh,默认就是这种方式)

如果以sh命令启动bashbash将模拟sh的行为,以~/.bash_开头的那些启动文件就不认了。

所以,如果作为交互登录Shell启动,或者使用--login参数启动,则依次执行以下文件:

/etc/profile⇒~/.profile

2.交互式非登录shell启动 

~/.bashrc

为什么登录Shell和非登录Shell的启动脚本要区分开呢?

最初的设计是这样考虑的,如果从字符终端或者远程登录,那么登录Shell是该用户的所有其它进程的父进程,也是其它子Shell的父进程,

所以环境变量在登录Shell的启动脚本里设置一次就可以自动带到其它非登录Shell里,

而Shell的本地变量、函数、alias等设置没有办法带到子Shell里,需要每次启动非登录Shell时设置一遍,

所以就需要有非登录Shell的启动脚本,所以一般来说在~/.bash_profile里设置环境变量,在~/.bashrc里设置本地变量、函数、alias等。

如果你的Linux带有图形系统则不能这样设置,由于从图形界面的窗口管理器登录并不会产生登录Shell,所以环境变量也应该在~/.bashrc里设置。

 3.非交互式启动

为执行脚本而fork出来的子Shell是非交互Shell,启动时执行的脚本文件由环境变量BASH_ENV定义,相当于自动执行以下命令:
    if [ -n "$BASH_ENV" ]; then
     . "$BASH_ENV";
     fi
如果环境变量BASH_ENV的值不是空字符串,则把它的值当作启动文件的文件名,source这个脚本。

通过sh,来fork非交互式shell,则

 if [ -n "$ENV" ]; then . "$ENV"; fi

一般来说,如果作为非交互Shell启动,则不执行任何启动脚本。通常我们写的Shell脚本都以#! /bin/sh开头,都属于这种方式。 

简单测试

[sabopeusr0-admin@localhost ~]$ grep tshell .bashrc
tshell="non-login shell will see this message"
export tshell
[sabopeusr0-admin@localhost ~]$ grep lshell .bash_profile
lshell="login shell will see this message"
export lshell
[sabopeusr0-admin@localhost ~]$ bash
[sabopeusr0-admin@localhost ~]$ echo $lshell

[sabopeusr0-admin@localhost ~]$ echo $tshell
non-login shell will see this message
[sabopeusr0-admin@localhost ~]$ exit
exit
[sabopeusr0-admin@localhost ~]$ bash --login
[sabopeusr0-admin@localhost ~]$ echo $lshell
login shell will see this message
[sabopeusr0-admin@localhost ~]$ echo $tshell
non-login shell will see this message
[sabopeusr0-admin@localhost ~]$