转关于“交互式-非交互式”与“登录-非登陆”shell的总结与关于“.bash_profile”和“.bashrc”区别的总结
关于“交互式-非交互式”与“登录-非登陆”shell的总结
关于“交互式-非交互式”与“登录-非登陆”shell的总结
Charles_Shih 2017-04-18 12:35:37 6339 收藏 11
分类专栏: Liunx 文章标签: bash shell linux
版权
运行中bash具有的两种属性
Linux shell是用户与Linux系统进行交互的媒介,而bash作为目前Linux系统中最常用的shell,它在运行时具有两种属性,即“交互”与“登陆”。
按照bash是否与用户进行交互,可以将其分为“交互式”与“非交互式”;而按照bash是否被用户登陆,又可将其分为“登陆shell”与“非登陆shell”。
“交互式”与“非交互式”
含义说明
交互式,是shell的一种运行模式,交互式shell等待你输入命令,并且立即执行,然后将结果反馈给你。这是每个CLI用户都非常熟悉的流程:登录、执行一些命令、登出。当你登出后,这个shell就终止了。
而非交互式,是shell的另一种运行模式,它专门被用来执行预先设定的命令。在这种模式下,shell不与用户进行交互,而是读取存放在脚本文件中的命令并执行它们。当它读到文件的结尾,这个shell就终止了。
启动方法
根据bash手册上的描述:
An interactive shell is one started without non-option arguments and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option.
从上面的描述看,只要执行bash命令的时候,不带有“选项以外的参数”或者-c选项,就会启动一个交互式shell。要理解这句话,就要弄懂“选项以外的参数”是什么意思,其实它指的就是shell的脚本文件;而-c选项将指定字符串作为命令读入bash,也就相当于执行指定的命令,它和前者有些类似,只是不从脚本文件中读取罢了。请看例子:
[chen@localhost Temp]$ echo "uname -r; date" > script.sh
[chen@localhost Temp]$ bash ./script.sh
3.10.0-514.el7.x86_64
Tue Apr 18 14:43:50 CST 2017
[chen@localhost Temp]$
[chen@localhost Temp]$ bash -c "uname -r; date"
3.10.0-514.el7.x86_64
Tue Apr 18 14:44:49 CST 2017
[chen@localhost Temp]$
1
2
3
4
5
6
7
8
9
通常来说,用于执行脚本的shell都是“非交互式”的,但我们也有办法把它启动为“交互式”shell,方法就是在执行bash命令时,添加-i选项:
[chen@localhost Temp]$ bash -c "echo \$-"
hBc
[chen@localhost Temp]$ bash -i -c "echo \$-"
himBHc
1
2
3
4
我们看到,添加了-i选项的bash -c命令为我们启动了一个“交互式”shell。
判别方法
根据bash手册上的描述:
PS1 is set and $- includes i if bash is interactive, allowing a shell script or a startup file to test this state.
用于在shell脚本和startup文件中判断当前shell“交互”属性的方法,就是判断变量PS1是否有值,或者判断变量$-是否包含i,请看例子:
[chen@localhost Temp]$ cat ./test1.sh
echo "\$0 : $0"
echo "\$- : $-"
echo "\$PS1 : $PS1"
[chen@localhost Temp]$ bash ./test1.sh # 非交互式shell
$0 : ./test1.sh
$- : hB
$PS1 :
[chen@localhost Temp]$ bash -i ./test1.sh # 交互式shell
$0 : ./test1.sh
$- : himB
$PS1 : [\u@\h \W]\$
[chen@localhost Temp]$
1
2
3
4
5
6
7
8
9
10
11
12
13
“登陆shell”与“非登陆shell”
含义说明
“登陆shell”通常指的是:
1. 用户通过输入用户名/密码(或证书认证)后启动的shell;
2. 通过带有-l|--login参数的bash命令启动的shell。
例如,系统启动、远程登录、使用su -切换用户、通过bash --login命令启动bash等。
而其他情况启动的shell基本上就都是“非登陆shell”了。
例如,从图形界面启动终端、使用su切换用户、通过bash命令启动bash等。
判别方法
根据bash手册上的描述:
A login shell is one whose first character of argument zero is a -, or one started with the --login option.
我们可以通过在shell中echo $0查看,显示-bash的一定是“登陆shell”,反之显示bash的则不好说。
[chen@localhost ~]$ bash --login
[chen@localhost ~]$ echo $0
bash
[chen@localhost ~]$
1
2
3
4
可以看出,使用bash --login启动的“登陆shell”,其$0也并非以-开头,这也就是为什么手册上的描述里使用“or”的原因。
另外,当我们执行exit命令退出shell时,也可以观察到它们的不同之处:
[chen@localhost ~]$ bash --login
[chen@localhost ~]$ exit # 退出登陆shell
logout
[chen@localhost ~]$ bash
[chen@localhost ~]$ exit # 退出非登陆shell
exit
[chen@localhost ~]$
1
2
3
4
5
6
7
原则上讲,我们使用logout退出“登陆shell”,使用exit退出“非登录shell”。但其实exit命令会判断当前shell的“登陆”属性,并分别调用logout或exit指令,因此使用起来相对方便。
主要区别
对于用户而言,“登录shell”和“非登陆shell”的主要区别在于启动shell时所执行的startup文件不同。
简单来说,“登录shell”执行的startup文件为~/.bash_profile,而“非登陆shell”执行的startup文件为~/.bashrc。
关于bash的startup文件,请参阅我的另一篇博客:
《关于“.bash_profile”和“.bashrc”区别的总结》
————————————————
版权声明:本文为CSDN博主「Charles_Shih」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sch0120/article/details/70226903
关于“.bash_profile”和“.bashrc”区别的总结
链接:https://blog.csdn.net/sch0120/article/details/70256318
bash的startup文件
Linux shell是用户与Linux系统进行交互的媒介,而bash作为目前Linux系统中最常用的shell,它支持的startup文件也并不单一,甚至容易让人感到费解。本文以CentOS7系统为例,对bash的startup文件进行一些必要的梳理和总结。
根据bash手册上的描述:
/etc/profile
The systemwide initialization file, executed for login shells
/etc/bash.bash_logout
The systemwide login shell cleanup file, executed when a login shell exits
~/.bash_profile
The personal initialization file, executed for login shells
~/.bashrc
The individual per-interactive-shell startup file
~/.bash_logout
The individual login shell cleanup file, executed when a login shell exits
此外,bash还支持~/.bash_login和~/.profile文件,作为对其他shell的兼容,它们与~/.bash_profile文件的作用是相同的。
备注:Debian系统会使用~/.profile文件取代~/.bash_profile文件,因此在相关细节上,会与CentOS略有不同。
“profile”与“rc”系列
通过名字的不同,我们可以直观地将startup文件分为“profile”与“rc”两个系列,其实他们的功能都很类似,但是使用的场景不同,这也是大家最容易忽略的地方。
所谓的不同场景,其实就是shell的运行模式。我们知道运行中的bash有“交互”和“登陆”两种属性,而执行“profile”系列还是“rc”系列,就与shell的这两个属性有关。
关于bash的运行模式,请参见我的另一篇博客:
《关于“交互式-非交互式”与“登录-非登陆”shell的总结》
原理上讲,“登陆shell”启动时会加载“profile”系列的startup文件,而“交互式非登陆shell”启动时会加载“rc”系列的startup文件。
“profile”系列的执行场景
根据bash手册上的描述:
When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.
When a login shell exits, bash reads and executes commands from the files ~/.bash_logout and /etc/bash.bash_logout, if the files exists.
“profile”系列的代表文件为~/.bash_profile,它用于“登录shell”的环境加载,这个“登录shell”既可以是“交互式”的,也可以是“非交互式”的。
通过--noprofile选项可以阻止系统加载“profile”系列的startup文件。
交互式登陆shell
对于交互式的登陆shell而言,CentOS规定了startup文件的加载顺序如下:
登陆过程:
1. 读取并执行/etc/profile文件;
2. 读取并执行~/.bash_profile文件;
- 若文件不存在,则读取并执行~/.bash_login文件;
- 若文件不存在,则读取并执行~/.profile文件;
登出过程:
1. 读取并执行~/.bash_logout文件;
2. 读取并执行/etc/bash.bash_logout文件;
为了完成实验,我新建了一些系统默认没有提供的startup文件,例如/etc/bash.bash_logout。然后在每个文件中打印了文件名,并将它们之间的显式调用语句注释掉,例如~/.bash_profile对~/.bashrc的显式调用。
“交互式登陆shell”的实验结果如下:
[root@localhost ~]# su - chen
Last login: Tue Apr 18 17:15:08 CST 2017 from 192.168.161.1 on pts/2
execute /etc/profile
execute ~/.bash_profile
-bash-4.2$ exit
logout
execute ~/.bash_logout
execute /etc/bash.bash_logout
[root@localhost ~]#
1
2
3
4
5
6
7
8
9
我们看到,因为执行了~/.bash_profile文件,所以优先级更低的~/.bash_login和~/.profile文件并没有被执行。
我们可以删除~/.bash_profile和~/.bash_login文件,这样系统就会找到并执行~/.profile文件:
[root@localhost ~]# mv /home/chen/.bash_profile /home/chen/.bash_profile.bak
[root@localhost ~]# mv /home/chen/.bash_login /home/chen/.bash_login.bak
[root@localhost ~]# su - chen
Last login: Tue Apr 18 17:27:21 CST 2017 on pts/1
execute /etc/profile
execute ~/.profile
-bash-4.2$ exit
logout
execute ~/.bash_logout
execute /etc/bash.bash_logout
[root@localhost ~]#
1
2
3
4
5
6
7
8
9
10
11
非交互式登陆shell
对于非交互式的登陆shell而言,CentOS规定了startup文件的加载顺序如下:
登陆过程:
1. 读取并执行/etc/profile文件;
2. 读取并执行~/.bash_profile文件;
- 若文件不存在,则读取并执行~/.bash_login文件;
- 若文件不存在,则读取并执行~/.profile文件;
我们注意到,与“交互式登陆shell”相比,“非交互式登陆shell”并没有登出的过程,实验也证实了这一点:
-bash-4.2$ bash --login -c "uname -r"
execute /etc/profile
execute ~/.bash_profile
3.10.0-514.el7.x86_64
-bash-4.2$ # 此时非交互式shell已退出
1
2
3
4
5
“rc”系列的执行场景
根据bash手册上的描述:
When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists. This may be inhibited by using the --norc option. The --rcfile file option will force bash to read and execute commands from file instead of ~/.bashrc.
“rc”系列的代表文件为~/.bashrc,它用于“交互式非登录shell”的环境加载。
通过--norc选项可以阻止系统加载“rc”系列的startup文件;通过--rcfile选项可以使用指定的文件替代系统默认的~/.bashrc文件。
交互式非登陆shell
对于交互式的非登陆shell而言,CentOS规定了startup文件的加载顺序如下:
1. 读取并执行~/.bashrc或--rcfile选项指定的文件
这里需要说明,其实“rc”系列startup文件还包括/etc/bashrc。但是系统并不直接调用这个文件,而是通过~/.bashrc文件显式地调用它。
为了完成实验,我在每个startup文件中打印了文件名,并将它们之间的显式调用语句注释掉,例如~/.bashrc对/etc/bashrc的显式调用。
“交互式非登陆shell”的实验结果如下:
[root@localhost ~]# su chen
execute ~/.bashrc
bash-4.2$ exit
exit
[root@localhost ~]#
1
2
3
4
5
startup文件的默认调用关系
细心的用户会发现,startup文件的加载并不像上面所述的那样简单。这是因为在CentOS中,startup文件之间还存在着默认的显式调用关系,它们是:
1. ~/.bash_profile显式调用~/.bashrc文件;
2. ~/.bashrc显式调用/etc/bashrc文件;
再看startup文件
分别打开/etc/profile和/etc/bashrc两个文件,我们可以看到:
[root@localhost ~]# head /etc/profile
# /etc/profile
# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc
# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.
[root@localhost ~]# head /etc/bashrc
# /etc/bashrc
# System wide functions and aliases
# Environment stuff goes in /etc/profile
# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
由此可见,“profile”系列文件的主要目的在于为“登录shell”设置环境变量和启动程序;而“rc”系列文件的主要目的在于设置功能和别名。
顺便提一句,Linux中“rc”是英文“run command”的缩写,表示文件中存放需要执行的命令。其实这也非常符合逻辑,设置功能就要执行shopt命令,而设置别名要执行alias命令。与“rc”系列互补,“profile”系列用来设置环境变量,它不会去调用这两个命令,但却经常需要使用export语句。不信你可以看一看这两个文件。
另外值得一提的是,这两个文件同时提到了一个位置:/etc/profile.d目录。这个目录用于存放个性化配置脚本,你可以把自己需要的全局配置放入以.sh结尾的文件中,系统在执行/etc/profile和/etc/bashrc文件时,都会择机调用它们。这样做最大的好处是便于维护,而且相对更加安全。
这些文件的编写方法,可以参考目录下已有的文件:
[root@localhost ~]# ls /etc/profile.d/*.sh
/etc/profile.d/256term.sh /etc/profile.d/colorls.sh /etc/profile.d/less.sh
/etc/profile.d/colorgrep.sh /etc/profile.d/lang.sh /etc/profile.d/which2.sh
1
2
3
总结
对于“登录shell”而言,“交互式”执行“登陆”和“登出”相关的“profile”系列startup文件,“非交互式”只执行“登陆”相关的“profile”系列startup文件;对于“非登陆shell”而言,“交互式”执行“rc”系列的startup文件,而“非交互式”执行的配置文件由环境变量BASH_ENV指定。
Linux中startup文件区分全局和个人:全局startup文件放在/etc目录下,用于设置所有用户共同的配置,除非你清楚地知道你在做的事情,否则不要轻易改动它们;个人startup文件放在~目录下,用于设置某个用户的个性化配置。
~/.bash_profile会显式调用~/.bashrc文件,而~/.bashrc又会显式调用/etc/bashrc文件,这是为了让所有交互式界面看起来一样。无论你是从远程登录(登陆shell),还是从图形界面打开终端(非登陆shell),你都拥有相同的提示符,因为环境变量PS1在/etc/bashrc文件中被统一设置过。
下面我来对startup文件进行一个完整的总结:
startup文件 交互登陆 非交互登陆 交互非登陆 非交互非登陆
/etc/profile 直接执行1 直接执行1 - -
~/.bash_profile 直接执行2 直接执行2 - -
~/.bash_login 条件执行2 条件执行2 - -
~/.profile 条件执行2 条件执行2 - -
~/.bash_logout 直接执行3 不执行 - -
/etc/bash.bash_logout 直接执行4 不执行 - -
~/.bashrc 引用执行2.1 引用执行2.1 直接执行1 -
/etc/bashrc 引用执行2.2 引用执行2.2 引用执行1.1 -
备注:
1. “直接执行”表示此文件被系统直接调用,它的执行是无条件的;
2. “条件执行”表示此文件被系统调用是有先决条件的(没有优先级更高的文件可用);
3. “引用执行”表示此文件不是被系统直接调用的,而是被其他文件显式调用的;
4. 后面的数字表示文件被调用的顺序,数字越大调用越靠后;
5. “非交互非登陆”shell的配置文件可以由BASH_ENV环境变量指定;
最后我想说的是,知道startup文件何时被执行并不是关键,关键是要理解自己的情况应该去修改哪个startup文件。
如果你想对bash的功能进行设置或者是定义一些别名,推荐你修改~/.bashrc文件,这样无论你以何种方式打开shell,你的配置都会生效。而如果你要更改一些环境变量,推荐你修改~/.bash_profile文件,因为考虑到shell的继承特性,这些更改确实只应该被执行一次(而不是多次)。针对所有用户进行全局设置,推荐你在/etc/profile.d目录下添加以.sh结尾的文件,而不是去修改全局startup文件。
————————————————
版权声明:本文为CSDN博主「Charles_Shih」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sch0120/article/details/70256318
首先非常感谢作者的付出,本人其实对于linux的操作一直玩的非常不666,处于超级菜鸟阶段。对与"登录与非登录"的shell前期一直陷入一个误区,非登录的状态是没有用户登录的。
看了作者的文章才慢慢的修正自己的错误观点,登录与非登录只不过是一个标签,更多的是通过这个标签,执行不同的启动脚本。
最后再次感谢作者的付出。