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]$
通常来说,用于执行脚本的shell都是“非交互式”的,但我们也有办法把它启动为“交互式”shell,方法就是在执行bash
命令时,添加-i
选项:
[chen@localhost Temp]$ bash -c "echo \$-"
hBc
[chen@localhost Temp]$ bash -i -c "echo \$-"
himBHc
我们看到,添加了-i
选项的bash -c
命令为我们启动了一个“交互式”shell。
根据bash手册上的描述:
PS1
is set and$-
includesi
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]$
“登陆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 ~]$
可以看出,使用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 ~]$
原则上讲,我们使用logout
退出“登陆shell”,使用exit
退出“非登录shell”。但其实exit
命令会判断当前shell的“登陆”属性,并分别调用logout
或exit
指令,因此使用起来相对方便。
对于用户而言,“登录shell”和“非登陆shell”的主要区别在于启动shell时所执行的startup文件不同。
简单来说,“登录shell”执行的startup文件为~/.bash_profile
,而“非登陆shell”执行的startup文件为~/.bashrc
。
关于bash的startup文件,请参阅我的另一篇博客:
《关于“.bash_profile”和“.bashrc”区别的总结》