[TOC]
# 简介
shell 是一个交互性命令解释器。
shell 独立于操作系统,Shell 俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器)。它类似于DOS 下的 command 和后来的 cmd.exe。它接收用户命令,然后调用相应的应用程序。
这种设计让用户可以灵活选择适合自己的 shell 。shell 让你在命令行键入命令,经过 shell 解释后传送给操作系统(内核)执行。
**shell是一个命令处理器(command processor)——是一个读入并解释你输入的命令的程序。**除了是一个命令中断器以外,shell 还是一个程序设计语言。你可以编写 shell 可以解释的程序(被称为源程序),这些源程序可以包含 shell 程序设计命令等等。shell 除了解释命令以外,还有其他工作,它也可以配置和编程。
shell 拥有自己的语言允许用户编写程序并以一种复杂方式运行。shell 编程语言具有许多常用的编程语言的特征,例如:循环和控制结构等。用户可以生成像其他应用程序一样复杂的 shell 程序。
## Linux Shell
Shell种类众多,常见的有:
**Bourne-Again shell** ( `/bin/bash`)
**Bourne shell** (` /usr/bin/sh`或`/bin/sh`,Stephen Bourne,1979年)
Korn shell ( usr/bin/ksh,David Korn,80年代中期)
POSIX shell ( sh)
Shell for Root(/sbin/sh)
C shell (包括 /usr/bin/csh and tcsh,Bill Joy,70年代末期)
TENEX/TOPS C shell ( tcsh)
...
**Bash**,也就是 Bourne Again Shell,由于易用和免费,Bash 在日常工作中被广泛使用。同时,Bash 也是大多数 Linux 系统默认的 Shell(GNU Bourne Again Shell)。
> 在一般情况下,人们并不区分 Bourne Shell 和 Bourne Again Shell,所以,像 `#!/bin/sh`,它同样也可以改为`#!/bin/bash`。
> `#!` 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。
# 系统中的 shell
其实 zsh 也是一种 shell ,但是并不是我们系统默认的 shell ,unix 衍生系统的默认 shell 都是 bash
我们看下系统内置了几种 shell:
```
$ cat /etc/shells
```
使用`bash -version` 命令来查看当前 shell 的版本号
查看当前用的是哪种 shell:
```
$ echo $0
```
更换系统的 shell 为 zsh:
~~~shell
chsh -s /bin/zsh
~~~
> [linux更换shell为zsh并个性化配置oh my zsh](https://cloud.tencent.com/developer/article/1135521)
# bashrc 与 profile
要搞清 bashrc 与 profile 的区别,首先要弄明白什么是交互式 shell 和非交互式 shell,什么是 login shell 和 non-login shell。
交互式模式就是 shell 等待你的输入,并且执行你提交的命令。这种模式被称作交互式是因为 shell 与用户进行交互。这种模式也是大多数用户非常熟悉的:登录、执行一些命令、签退。当你签退后,shell 也终止了。
shell 也可以运行在另外一种模式:非交互式模式。在这种模式下,shell 不与你进行交互,而是读取存放在文件中的命令,并且执行它们。当它读到文件的结尾,shell 也就终止了。
bashrc 与 profile 都用于保存用户的环境信息,bashrc用于交互式 non-loginshell,而 profile 用于交互式 login shell。
## 识别 login shell
要识别一个shell是否为login shell,只需在该shell下执行:
```
# echo $0
```
如果输出为该 shell 名字,加上一个'-'前缀,则说明该 shell 为 login shell,没有'-'前缀则是 no login。
1. 当 bash 以 login shell 启动时,它会执行`/etc/profile`中的命令,然后`/etc/profile`调用`/etc/profile.d`目录下的所有脚本;然后执行`~/.bash_profile`,`~/.bash_profile`中显式调用`~/.bashrc`,最后`~/.bashrc`又调用`/etc/bashrc`。
2. 非 login 方式启动时,它会调用`~/.bashrc`,随后`~/.bashrc`中调用`/etc/bashrc`,最后`/etc/bashrc`调用所有`/etc/profile.d`目录下的脚本。
## profile 文件
系统中存在许多 bashrc 和 profile 文件,下面逐一介绍:
| 文件 | 描述 |
| --- | --- |
| `/etc/profile` | 此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行。并从`/etc/profile.d`目录的配置文件中搜集 shell 的设置。|
| `/etc/bashrc` | 为每一个运行`bash` shell的用户执行此文件。当``bash``shell被打开时,该文件被读取。|
| `~/.bashrc` | 该文件包含专用于你的 bash shell 的 bash 信息,当登录时以及每次打开新的 shell 时,该文件被读取。 |
| `~/.profile`或者`~/.bash_profile` | 用户可以使用该文件输入自己需要使用的 shell 信息,当用户登录时,该文件仅仅执行一次!默认情况下,它设置一些环境变量,执行用户的`.bashrc`文件。|
| `~/.bash_logout` | 当每次退出系统(退出``bash``shell)时,执行该文件。 |
> 注意:`.profile`是 unix 上才有的;`.bash_profile`是 Linux 下有的(Linux下,用户目录没有`.profile`文件) 。
> 另外,`/etc/profile`中设定的变量(全局)的可以作用于任何用户,而`~/.bashrc`等中设定的变量(局部)只能继承`/etc/profile`中的变量,他们是``"父子"``关系。
> [交互式shell和非交互式shell、登录shell和非登录shell的区别](https://blog.csdn.net/airings/article/details/8756938)
> [深入浅出理解交互式shell和非交互式shell、登录shell和非登录shell的区别](https://blog.csdn.net/gui951753/article/details/79154496)
## `.bash_profile`进行个性化设置
每次修改`.bashrc`后,使用`source ~/.bashrc`(或者`. ~/.bashrc`)就可以立刻加载修改后的设置,使之生效。
一般会在`.bash_profile`文件中显式调用`.bashrc`。登陆 linux 启动 bash 时首先会去读取`~/.bash_profile`文件,这样`~/.bashrc`也就得到执行了,你的个性化设置也就生效了。
利用这一特性,可以实现一些个性化设置,如:Linux 系统开机执行自动某个脚本文件等,这在自动化运维方面有一定的用处。
1. 修改`/home/bing/.bashrc`文件:
~~~
sudo vim /home/bing/.bashrc
# 在最后添加两句后保存
echo '这句话开机就会启动' # 打印输出
python3 /home/bing/test.py # 执行 test.py 这个脚本,打印输出 hello world!
~~~
2. 当 Linux 开机后:
```shell
这句话开机就会启动
hello world!
```
可以看到 Linux 开机后加载了`.bashrc`文件。
> [Linux 中 bashrc 中的 rc 是什么意思](https://blog.csdn.net/u010167269/article/details/52612260)
# shell 功能
以下是shell 功能的一个汇总:
查找命令的位置并且执行相关联的程序;
为shell变量赋新值;
执行命令替代;
处理 I/O重定向和管道功能;
提供一个解释性的编程语言界面,包括tests、branches和loops等语句。
当你在命令行中敲入bash命令时,相当于进入bash环境,如果本身就是bash环境,那么就是进入一个子bash环境(相当于开了一个子进程)。
参考:http://bbs.chinaunix.net/thread-2325808-1-1.html
# 特殊符号
当我们需要一次执行多个命令的时候,命令之间需要用连接符连接,不同的连接符有不同的效果。下面我们总结一下,加以区分。
(1) `;`
分号,没有任何逻辑关系的连接符。当多个命令用分号连接时,各命令之间的执行成功与否彼此没有任何影响,都会一条一条执行下去。
(2) `||`
逻辑或,当用此连接符连接多个命令时,前面的命令执行成功,则后面的命令不会执行。前面的命令执行失败,后面的命令才会执行。
(3) `&&`
逻辑与,当用此连接符连接多个命令时,前面的命令执行成功,才会执行后面的命令,前面的命令执行失败,后面的命令不会执行,与 || 正好相反。
(4) `|`
管道符,当用此连接符连接多个命令时,前面命令执行的正确输出,会交给后面的命令继续处理。若前面的命令执行失败,则会报错,若后面的命令无法处理前面命令的输出,也会报错。
例`ls | grep *.txt`
# 参考
> [第十一章、认识与学习BASH](http://cn.linux.vbird.org/linux_basic/0320bash.php)
https://blog.csdn.net/wenlifu71022/article/details/4069929
http://blog.csdn.net/ClementAD/article/details/46793827
http://blog.csdn.net/sinat_30196907/article/details/48436979
http://blog.csdn.net/hack8/article/details/39672145
http://blog.csdn.net/duguduchong/article/details/8486663
http://blog.csdn.net/OldHusband/article/details/69058143
http://blog.csdn.net/sjl110/article/details/72628869
http://blog.csdn.net/China_Guanq/article/details/51726842
http://blog.csdn.net/qq_35242986/article/details/73772212