作者:Sam (甄峰) sam_code@hotmail.com
0. Bash的运行模式:
运行中的Bash有两种属性(模式)。 A:是否Interactive shell(交互式Shell)。
B:是否Login shell(登陆shell).
当这两项模式排列组合后,就会出现4种运行模式。
1. 登录交互式Shell。
2. 非登录交互式Shell。
3. 登陆非交互式Shell。
4. 非登录非交互式Shell。
1. Bash运行模式具体介绍:
1.1:Login Shell:
login shell是指用户以非图形化界面或者以ssh登陆到机器上时获得的第一个shell,简单些说就是需要输入用户名和密码的shell。因此通常不管以何种方式登陆机器后用户获得的第一个shell就是login
shell。
在下列情况下,我们可以获得一个login shell:
- 登录系统时获得的顶层shell,无论是通过本地终端登录,还是通过网络ssh登录。这种情况下获得的login shell是一个交互式shell。
- 在终端下使用--login选项调用bash,可以获得一个交互式login shell。
- 在脚本中使用--login选项调用bash(比如在shell脚本第一行做如下指定:#!/bin/bash --login),此时得到一个非交互式的login shell。
- 使用"su -"切换到指定用户时,获得此用户的login shell。如果不使用"-",则获得non-login shell。
login shell与non-login shell的主要区别在于它们启动时会读取不同的配置文件,从而导致环境不一样。login
shell启动时首先读取/etc/profile全局配置,然后依次查找~/.bash_profile、~/.bash_login、~/.profile三个配置文件,并且读取第一个找到的并且可读的文件。login
shell退出时读取并执行~/.bash_logout中的命令。
1.2:Interactive Shell
(交互Shell):
interactive
shell会有一个输入提示符,并且它的标准输入、输出和错误输出都会显示在控制台上。所以一般来说只要是需要用户交互的,即一个命令一个命令的输入的shell都是interactive
shell。而如果无需用户交互,它便是non-interactive shell。
怎样得到一个交互式Shell呢?
没有非选项参数,没有-c,标准输入和标准输出与终端相连的,或者用-i参数启动的Bash实例。
例如在Bash Shell中,使用bash命令启动一个shell.
就是一个交互式(但非Login)Shell。
如何得到一个非交互式Shell:
bash run.sh 这样执行shell脚本的实例, 即为非交互式Shell.它不需要与用户交互,在运行完脚本后,就退出所创建的非交互Shell了。
1.3: 排列组合的讲解:
1.3.1: Interactive Login Shell:
1. 正常登录字符界面
2. 远程使用ssh等登录。
3. 在终端下使用bash --login 调用bash.
4. su xxx .
都会进入Interactive Login Shell.
配置文件的加载:shell首先加载/etc/profile
,然后再尝试依次去加载下列三个配置文件之一,一旦找到其中一个便不再接着寻找:
- ~/.bash_profile
- ~/.bash_login
- ~/.profile
实际使用例子:在修改完:~/.profile 或 ~/.bashrc后,Sam通常会 bash --login (bash -l) ,
调用一个login bash, 它依次取了新配置的配置文件。
这里就会有疑问:关~/.bashrc什么事?前面不是没提到它么? 但在~/.profile中,可以看到:
. "$HOME/.bashrc"
在这里把 .bashrc配置加入了。
1.3.2:Non-Interactive + Login Shell:
很少见,
在命令行或脚本中:
bash -l run.sh
-l : Login Shell.
执行脚本,又让这个Shell 成为:Non-Interactive。
配置文件加载与之前类似。
1.3.3: Interactive + Non-Login
Shell:
在命令行或脚本中,运行bash. 此时会打开一个交互式Shell. 但因为没有 -l,
所以是非登录Shell。
会去查找和加载:/etc/bash.bashrc 和
~/.bashrc.
1.3.4:Non-Interactive + Non-Login Shell:
最后一种模式为非交互非登陆的shell,创建这种shell典型有两种方式:
- bash script.sh
- ssh user@remote command
这两种都是创建一个shell,执行完脚本之后便退出,不再需要与用户交互。
对于这种模式而言,它会去寻找环境变量
BASH_ENV
,将变量的值作为文件名进行查找,如果找到便加载它。
而BASH_EVN 很多多情况下,都是空。所以环境最缺乏。
更为直观的示图
至此,四种模式下配置文件如何加载已经讲完,因为涉及的配置文件有些多,我们再以两个图来更为直观的进行描述:
第一张图来自这篇文章,bash的每种模式会读取其所在列的内容,首先执行A,然后是B,C。而B1,B2和B3表示只会执行第一个存在的文件:
+----------------+--------+-----------+---------------+
| | login |interactive|non-interactive|
| | |non-login |non-login |
+----------------+--------+-----------+---------------+
|/etc/profile | A | | |
+----------------+--------+-----------+---------------+
|/etc/bash.bashrc| | A | |
+----------------+--------+-----------+---------------+
|~/.bashrc | | B | |
+----------------+--------+-----------+---------------+
|~/.bash_profile | B1 | | |
+----------------+--------+-----------+---------------+
|~/.bash_login | B2 | | |
+----------------+--------+-----------+---------------+
|~/.profile | B3 | | |
+----------------+--------+-----------+---------------+
|BASH_ENV | | | A |
+----------------+--------+-----------+---------------+