shell/shell.md

705 lines
31 KiB
Markdown
Raw Permalink Normal View History

2025-03-28 20:09:53 +08:00
<h2><center>Shell</center></h2>
------
## 一Shell 概述
### 1. shell 定义
Shell 中文含义是“壳”它是相对于内核来说的因为它是建立在内核的基础上面向用户的一种表现形式比如我们看到一个球见到的是它的壳而非核。Linux中的Shell是指一个面向用户的命令接口表现形式就是一个可以由用户录入的界面这个界面也可以反馈运行信息。
Shell 是命令解释器,用于与操作系统交互,用来完成各种任务,如文件操作、系统管理、网络管理等。
Shell 是一种程序设计语言他有变量有自己的语法结构等shell程序设计语言可以编写功能很强、代码简短的程序
### 2. Shell 在 Linux 中的存在形式
由于 Linux 不同于 WindowsLinux 是内核与界面分离的,它可以脱离图形界面而单独运行,同样也可以在内核的基础上运行图形化的桌面。 这样在Linux 系统中,就出现了两种 Shell 表现形式,一种是在无图形界面下的终端运行环境下的 Shell另一种是桌面上运行的类似 Windows 的 MS-DOS 运行窗口。
### 3. Shell 如何执行用户的指令
Shell 有两种执行指令的方式
- 第一种方法是用户事先编写一个 sh 脚本文件,内含 Shell 脚本,而后使用 Shell 程序执行该脚本,这种方式,我们习惯称为 Shell 编程。
- 第二种形式则是用户直接在Shell界面上执行 Shell 命令,由于 Shell 界面的关系,大家都习惯一行行的书写,很少写出成套的程序来一起执行,所以也称命令行。
**总结:**
Shell 只是为用户与机器之间搭建成的一个桥梁让我们能够通过Shell来对计算机进行操作和交互从而达到让计算机为我们服务的目的。
### 4. Shell 分类
Linux中默认Shell是bash流行的Shell有ash、bash、ksh、csh、zsh等不同的Shell都有自己的特点以及用途。
**Bash**
大多数Linux系统默认使用的Shellbash Shell是Bourne Shell 的一个免费版本它是最早的Unix Shell,bash还有一个特点可以通过help命令来查看帮助。包含的功能几乎可以涵盖Shell所具有的功能所以一般的Shell脚本都会指定它为执行路径。
**Csh**
C Shell 使用的是“类C”语法csh 是具有C语言风格的一种 Shell其内部命令有52个较为庞大。**目前使用的并不多,已经被`/bin/tcsh`所取代**。
**Ksh**
Korn Shell 的语法与 Bourne Shell 相同,同时具备了 C Shell 的易用特点。许多安装脚本都使用 kshksh 有42条内部命令**与 bash 相比有一定的限制性**。
**TCsh**
tcsh 是 csh 的增强版与C Shell完全兼容。
**Sh**
是一个快捷方式,已经被`/bin/bash`所取代。
**Nologin**
指用户不能登录
**Zsh**
前 Linux 里最庞大的一种 zsh。它有84个内部命令使用起来也比较复杂。一般情况下不会使用该Shell。
### 5. Shell 使用场景
- 自动化批量系统初始化程序 update软件安装时区设置安全策略...
- 自动化批量软件部署程序 LAMPLNMPTomcatLVSNginx
- 应用管理程序 (KVM集群管理扩容MySQLDELLR720批量RAID
- 日志分析处理程序PV, UV, 200, !200, top 100, grep/awk
- 自动化备份恢复程序MySQL完全备份/增量 + Crond
- 自动化管理程序(批量远程修改密码,软件升级,配置更新)
- 自动化信息采集及监控程序(收集系统/应 用状态信息CPU,Mem,Disk,Net,TCP Status,Apache,MySQL
- 配合Zabbix信息采集收集系统/应用状态信息CPU,Mem,Disk,Net,TCP Status,Apache,MySQL
- 自动化扩容(增加云主机-->业务上线)
- Zabbix监控CPU 80%+|-50% Python API AWS/EC2增加/删除云主机) + Shell Script业务上线
- 俄罗斯方块,打印三角形,打印圣诞树,打印五角星,运行小火车,坦克大战,排序算法实现
- “Shell可以做任何事”一切取决于业务需求
### 6. Bash 初始化
**Bash 环境变量文件的加载**
```shell
/etc/profile 使用范围:所有账户
/etc/bashrc 使用范围:所有账户
~/.bashrc 使用范围:~所代表的账户
~/.bash_profile 使用范围:~所代表的账户
~/.bash_logout
login shell
登录的时候需要输入用户名
nologin shell
登录的时候不需要输入用户
```
1. **`/etc/profile`**:全局配置,每个用户登录时都会读取该文件。
2. **`/etc/bashrc`**全局配置Ubuntu 没有此文件,与之对应的是 `/ect/bash.bashrc`bash 执行时,不管是何种方式,都会读取此文件。
3. **`~/.profile`**:若`bash`是以`login`方式执行,读取`~/.bash_profile`,若它不存在,则读取`~/.bash_login`,若前两者不存在,读取`~/.profile`。图形模式登录时,此文件将被读取,即使存在`~/.bash_profile``~/.bash_login`
4. **`~/.bash_login`**:若`bash`是以`login`方式执行时,读取`~/.bash_profile`,若它不存在,则读取`~/.bash_login`,若前两者不存在,读取`~/.profile`
5. **`~/.bash_profile`**Unbutu 默认没有此文件,可新建。只有`bash`是以`login`形式执行时,才会读取此文件。通常该配置文件还会配置成去读取 `~/.bashrc`
6. **`~/.bashrc`**:当 bash 是以`non-login`形式执行时,读取此文件。若是以`login`形式执行,则不会读取此文件。
7. **`~/.bash_logout`**:当 bash 是以`non-login`形式执行时,读取此文件。若是以`login`形式执行,则不会读取此文件。
**Bash 环境变量加载**
- 图形模式登录时,顺序读取:/etc/profile 和 ~/.profile
- 图形模式登录后,打开终端时,顺序读取:/etc/bash.bashrc 和 ~/.bashrc
- 文本模式登录时,顺序读取:/etc/bash.bashrc/etc/profile 和 ~/.bash_profile
- 从其它用户 su 到该用户,则分两种情况:
- 如果带 -l 参数(或-参数,--login 参数su -l username则 bash 是 login 的,它将顺序读取以下配置文件:/etc/bash.bashrc/etc/profile 和~/.bash_profile。
- 如果没有带 -l 参数,则 bash 是 non-login 的,它将顺序读取:/etc/bash.bashrc 和 ~/.bashrc
- 注销时,或退出 su 登录的用户,如果是 longin 方式,那么 bash 会读取:~/.bash_logout
- 执行自定义的 Shell 文件时,若使用 bash -l a.sh 的方式,则 bash 会读取行:/etc/profile 和 ~/.bash_profile若使用其它方式bash a.sh./a.shsh a.sh这个不属于bash Shell则不会读取上面的任何文件。
- 上面的例子凡是读取到 ~/.bash_profile 的,若该文件不存在,则读取 ~/.bash_login若前两者不存在读取 ~/.profile。
## 二Bash 特性
### 1. 自动补全
很多命令都会提供一个`bash-complete`的脚本,在执行该命令时,敲`tab`可以自动补全参数,会极大提高生产效率。
`linux`命令自动补全需要安装`bash-completion`
```bash
# yum install -y bash-completion
```
默认情况下,`Bash``Linux`用户提供了下列标准补全功能。
- 变量补全
- 用户名补全
- 主机名补全
- 路径补全
- 文件名补全
### 2. 历史命令
- `Bash`有自动记录命令的功能,自动记录到`.bash_history`隐藏文件中。还可以在下次需要是直接调用历史记录中的命令。
- `Centos`可以通过`/etc/profile`中的文件来定义一些参数。
-`bash`中,使用`history`命令来查看和操作之前的命令,以此来提高工作效率。
- `history``bash`的内部命令,所以可以使用`help history`命令调出`history`命令的帮助文档。
- 获取某一条历史命令:`!number` 直接执行对应序号的命令。
- 快捷键调用历史命令:`Ctrl+r`输入关键字调出之前的命令。
```bash
# 查看之前使用的所有命令
[root@wxin ~]# history
# 显示最近的n个命令
[root@wxin ~]# history n
# 删除相应的第n个命令
[root@wxin ~]# history -d n
# 指定执行命令历史中的第n条语句
[root@wxin ~]# !n
# 指定执行命令历史中倒数第n条语句
[root@wxin ~]# !-n
# 执行命令历史中最后一条语句
[root@wxin ~]# !!
# 执行命令历史中最近一条以[String]开头的语句
[root@wxin ~]# ![String]
# 引用上一个命令中的最后一个参数
[root@wxin ~]# !$
# COMMAND + Esc键 + . 输入COMMAND之后,按下Esc键,松开后再按 . 则可以自动输入最近一条语句使用的参数
*# COMMAND + Alt + . 输入COMMAND之后,同时按下Alt和. 键,也可以自动输入最近一条语句使用的参数
# 将命令历史写入命令历史的文件中
[root@wxin ~]# history -w
# 回显 echo 之后的语句,而使用 echo $FILENAME 命令可以查看该 file 所在的路径
[root@wxin ~]# echo $HISTFILE
[root@wxin ~]# echo $HISTSIZE
# 查看命令历史的内容
[root@wxin ~]# cat .bash_history
# 删除所有的命令历史记录
[root@wxin ~]# history -c
```
### 3. 别名
`alias`命令,别名的好处是可以把本来很长的指令简化缩写,来提高工作效率。
```bash
[root@wxin ~]# alias #查看系统当前所有的别名
[root@wxin ~]# alias h5=head -5 #定义新的别名。这时候输入h5就等于输入head-5
[root@wxin ~]# unalias h5 #取消别名定义
```
如果想要文件永久生效,只需将上述别名命令写到对应用户或者系统`bashrc`文件中。
如果想用真实命令可以在命令前面添加反斜杠 ,使别名失效 。
```bash
[root@wxin ~]# \cp -rf /etc/hosts
```
### 4. 快捷键
**命令行编辑**
| 快捷键 | 作用 |
| :---------: | :--------------------------: |
| `Ctrl + a` | 将光标移动到行首 |
| `Ctrl + e` | 将光标移动到行尾 |
| `Ctrl + b` | 光标向左移动一个字符 |
| `Ctrl + f` | 光标向右移动一个字符 |
| `Alt + b` | 光标向左移动一个单词 |
| `Alt + f` | 光标向右移动一个单词 |
| `Ctrl + xx` | 在行首和当前光标位置之间切换 |
| `Ctrl + t` | 交换光标前两个字符的位置 |
| `Ctrl + w` | 删除光标前的一个单词 |
| `Ctrl + u` | 删除从光标到行首的所有内容 |
| `Ctrl + k` | 删除从光标到行尾的所有内容 |
| `Ctrl + y` | 粘贴最近一次删除的内容 |
| `Ctrl + -` | 撤销上一次操作 |
**历史命令操作**
| 快捷键 | 作用 |
| :--------------------: | :--------------------------: |
| `Ctrl + p` | 显示上一条历史命令 |
| `Ctrl + n` | 显示下一条历史命令 |
| `Ctrl + r` | 反向搜索历史命令 |
| `Ctrl + g` | 退出反向搜索历史模式 |
| `Alt + .``Esc + .` | 插入上一条命令的最后一个参数 |
| `!!` | 执行上一条命令 |
| `!n` | 执行历史记录中第 `n` 条命令 |
**进程控制**
| 快捷键 | 作用 |
| ---------- | -------------------------------------- |
| `Ctrl + c` | 终止当前正在运行的命令 |
| `Ctrl + d` | 发送 EOF文件结束符退出当前 Shell |
| `Ctrl + z` | 挂起当前进程(放入后台) |
| `Ctrl + l` | 清屏(等同 `clear` 命令) |
### 5. 前后台作业控制
`bash`单一终端界面下,经常需要管理或同时完成多个作业,如一边执行编译,一边实现数据备份,以及执行`SQL`查询等其他的任务。所有的上述的这些工作可以在一个`bash`内实现,在同一个终端窗口完成。
通过`jobs`方式来管理作业,当前终端的作业在其他终端不可见。
#### 1. 前后台作业的定义
- 前后台作业实际上对应的也就是前后台进程,因此也就有对应的`pid`。在这里统称为作业。
- 无论是前台作业还是后台作业,两者都来自当前的`Shell`,是当前`Shell`的子程序。
- 前台作业:可以由用户参与交互及控制的作业我们称之为前台作业。
- 后台作业:在内存可以自运行的作业,用户无法参与交互以及使用`[ctrl]+c`来终止,只能通过`bg``fg`来调用该作业。
#### 2. 作业命令
| 命令 | 作用 |
| :---------: | :----------------------------------------: |
| `&` | 在命令末尾添加 `&` 即可后台运行 |
| `jobs` | 显示当前会话的任务列表 |
| `fg %n` | 将任务 `n` 切到前台 |
| `bg %n` | 将任务 `n` 切到后台继续运行 |
| `Ctrl + z` | 暂停当前前台任务,任务状态变为 `suspended` |
| `kill + %n` | 移除指定的作业n |
- 任务编号前的 `+` 表示最近操作的任务,`-` 表示次近任务。
**示例:**
```bash
[root@wxin ~]# sleep 10000 &
[1] 2787
[root@wxin ~]# jobs
[1]+ 运行中 sleep 10000 &
[root@wxin ~]# sleep 30000 &
[2] 2800
[root@wxin ~]# jobs
[1]- 运行中 sleep 10000 &
[2]+ 运行中 sleep 30000 &
[root@wxin ~]# sleep 60000 &
[3] 2813
[root@wxin ~]# jobs
[1] 运行中 sleep 10000 &
[2]- 运行中 sleep 30000 &
[3]+ 运行中 sleep 60000 &
[root@wxin ~]# fg %1
sleep 10000
^Z
[1]+ 已停止 sleep 10000
[root@wxin ~]# bg %1
[1]+ sleep 10000 &
[root@wxin ~]# jobs
[1] 运行中 sleep 10000 &
[2]- 运行中 sleep 30000 &
[3]+ 运行中 sleep 60000 &
[root@wxin ~]# kill %1
[1] 已终止 sleep 10000
[root@wxin ~]# kill -15 %2
[2]- 已终止 sleep 30000
[root@wxin ~]# kill -9 %3
[3]+ 已杀死 sleep 60000
```
#### 3. 作业脱机管理
- 作业(进程)切换到后台可以避免由于误操作如`[ctrl] + c`等导致的job被异常中断的情形而脱机管理主要是针对终端异常断开的情形。
- 通常使用`nohup`命令来使得脱机或注销之后,`Job`依旧可以继续运行。也就是说`nohup`忽略所有挂断SIGHUP信号。
- 如果该方式命令之后未指定`&`符号,则`job`位于前台,指定`&`符号,则`job`位于后台。
#### 4. Screen 命令使用
**简介**
Screen 是一款由GNU计划开发的用于命令行终端切换的自由软件。用户可以通过该软件同时连接多个本地或远程的命令行会话并在其间自由切换。GNU Screen可以看作是窗口管理器的命令行界面版本。它提供了统一的管理多个会话的界面和相应的功能。
- **会话恢复:**只要`Screen`本身没有终止,在其内部运行的会话都可以恢复。这一点对于远程登录的用户特别有用——即使网络连接中断,用户也不会失去对已经打开的命令行会话的控制。只要再次登录到主机上执行`screen -r`就可以恢复会话的运行。同样在暂时离开的时候,也可以执行分离命令`detach`,在保证里面的程序正常运行的情况下让`Screen`挂起(切换到后台)。这一点和图形界面下的`VNC`很相似。
- **多窗口:**在`Screen`环境下,所有的会话都独立的运行,并拥有各自的编号、输入、输出和窗口缓存。用户可以通过快捷键在不同的窗口下切换,并可以自由的重定向各个窗口的输入和输出。`Screen`实现了基本的文本操作,如复制粘贴等;还提供了类似滚动条的功能,可以查看窗口状况的历史记录。窗口还可以被分区和命名,还可以监视后台窗口的活动。 会话共享`Screen`可以让一个或多个用户从不同终端多次登录一个会话,并共享会话的所有特性(比如可以看到完全相同的输出)。它同时提供了窗口访问权限的机制,可以对窗口进行密码保护。
**安装 `screen`**
流行的Linux发行版例如Red Hat Enterprise Linux通常会自带screen实用程序如果没有的话可以从GNU screen的官方网站下载。
```bash
[root@wxin ~]# yum install -y screen
```
**语法**
```shell
screen [-AmRvx -ls -wipe][-d <作业名称>][-h <行数>][-r <作业名称>][-s ][-S <作业名称>]
-A  将所有的视窗都调整为目前终端机的大小。
-d <作业名称>  将指定的screen作业离线。
-h <行数>  指定视窗的缓冲区行数。
-m  即使目前已在作业中的screen作业仍强制建立新的screen作业。
-r <作业名称>  恢复离线的screen作业。
-R  先试图恢复离线的作业。若找不到离线的作业即建立新的screen作业。
-s  指定建立新视窗时所要执行的Shell。
-S <作业名称>  指定screen作业的名称。
-v  显示版本信息。
-x  恢复之前离线的screen作业。
-ls或--list  显示目前所有的screen作业。
-wipe  检查目前所有的screen作业并删除已经无法使用的screen作业。
```
示例:
```bash
[root@wxin ~]# screen -S yourname # 新建一个叫yourname的session
[root@wxin ~]# screen -ls # 列出当前所有的session
[root@wxin ~]# screen -r yourname # 回到yourname这个session
[root@wxin ~]# screen -d yourname # 远程detach某个session
[root@wxin ~]# screen -d -r yourname # 结束当前session并回到yourname这个session
```
**在`Session`下,使用`Ctrl + a` C-a**
```shell
C-a ? # 显示所有键绑定信息
C-a c # 创建一个新的运行Shell的窗口并切换到该窗口
C-a n # Next切换到下一个 window
C-a p # Previous切换到前一个 window
C-a 0..9 # 切换到第 0..9 个 window
Ctrl+a [Space] # 由视窗0循序切换到视窗9
C-a C-a # 在两个最近使用的 window 间切换
C-a x # 锁住当前的 window需用用户密码解锁
C-a d # detach暂时离开当前session将目前的 screen session (可能含有多个 windows) 丢到后台执行,并会回到还没进 screen 时的状态,此时在 screen session 里,每个 window 内运行的 process (无论是前台/后台)都在继续执行,即使 logout 也不影响。
C-a z # 把当前session放到后台执行用 Shell 的 fg 命令则可回去。
C-a w # 显示所有窗口列表
C-a t # time显示当前时间和系统的 load
C-a k # kill window强行关闭当前的 window
C-a [ # 进入 copy mode在 copy mode 下可以回滚、搜索、复制就像用使用 vi 一样
C-b BackwardPageUp
C-f ForwardPageDown
H(大写) High将光标移至左上角
L Low将光标移至左下角
0 移到行首
$ 行末
w forward one word以字为单位往前移
b backward one word以字为单位往后移
Space 第一次按为标记区起点,第二次按为终点
Esc 结束 copy mode
C-a ] # paste把刚刚在 copy mode 选定的内容贴上
```
**常用操作**
- 创建会话(-m 强制)
```bash
[root@wxin ~]# screen -dmS session_name # session_name session名称
```
- 关闭会话
```bash
[root@wxin ~]# screen -X -S [session # you want to kill] quit
```
- 查看所有会话
```bash
[root@wxin ~]# screen -ls
```
- 进入会话
```bash
[root@wxin ~]# screen -r session_name
```
- 清楚`dead`会话
如果由于某种原因其中一个会话死掉了(例如人为杀掉该会话),这时`screen -list`会显示该会话为`dead`状态。使用`screen -wipe`命令清除该会话。
- 关闭或杀死窗口
1. 正常情况下当你退出一个窗口中最后一个程序通常是bash这个窗口就关闭了。另一个关闭窗口的方法是使用C-a k这个快捷键杀死当前的窗口同时也将杀死这个窗口中正在运行的进程。
2. 如果一个Screen会话中最后一个窗口被关闭了那么整个Screen会话也就退出了screen进程会被终止。
3. 除了依次退出/杀死当前`Screen`会话中所有窗口这种方法之外还可以使用快捷键C-a :,然后输入`quit`命令退出`Screen`会话。需要注意的是,这样退出会杀死所有窗口并退出其中运行的所有程序。其实`C-a`:这个快捷键允许用户直接输入的命令有很多,包括分屏可以输入[split](http://man.linuxde.net/split)等,这也是实现`Screen`功能的一个途径,不过个人认为还是快捷键比较方便些。
### 6. 输入输出重定向
一般情况下计算机从键盘读取用户输入的数据然后再把数据拿到程序C语言程序、Shell 脚本程序等)中使用;这就是标准的输入方向,也就是从键盘到程序。
程序中产生数据直接呈现到显示器上,这就是标准的输出方向,也就是从程序到显示器。输入输出方向就是数据的流动方向:
- 输入方向就是数据从哪里流向程序。数据默认从键盘流向程序,如果改变了它的方向,数据就从其它地方流入,这就是输入重定向。
- 输出方向就是数据从程序流向哪里。数据默认从程序流向显示器,如果改变了它的方向,数据就流向其它地方,这就是输出重定向。
#### 1. 文件描述符
又称文件句柄
计算机的硬件设备有很多,常见的输入设备有键盘、鼠标等,输出设备有显示器、投影仪、打印机等。不过,在 Linux中标准输入设备指的是键盘标准输出设备指的是显示器。
- Linux 中一切皆文件,包括标准输入设备(键盘)和标准输出设备(显示器)在内的所有计算机硬件都是文件。
- 为了表示和区分已经打开的文件Linux 会给每个文件分配一个 ID这个 ID 就是一个整数被称为文件描述符File Descriptor
| 文件描述符(文件句柄) | 文件名 | 类型 | 硬件 |
| ---------------------- | ------ | ---------------- | ------ |
| 0 | stdin | 标准输入文件 | 键盘 |
| 1 | stdout | 标准正确输出文件 | 显示器 |
| 2 | stderr | 标准错误输出文件 | 显示器 |
- Linux 程序在执行任何形式的 I/O 操作时都是在读取或者写入一个文件描述符。一个文件描述符只是一个和打开的文件相关联的整数它的背后可能是一个硬盘上的普通文件、FIFO、管道、终端、键盘、显示器甚至是一个网络连接。
- stdin、stdout、stderr 默认都是打开的在重定向的过程中0、1、2 这三个文件描述符可以直接使用。
#### 2. 输出重定向
输出重定向是指命令的结果不再输出到显示器上而是输出到其它地方一般是文件中。这样做的最大好处就是把命令的结果保存起来当我们需要的时候可以随时查询。Bash 支持的输出重定向符号如下表所示。
- 输出重定向中,> 代表的是覆盖,>> 代表的是追加。
- 输出重定向的完整写法其实是 fd>file 或者 fd>>file ,其中 fd 表示文件描述符,如果不写,默认为 1也就是标准输出文件。
- 当文件描述符为 1 时,一般都省略不写,如上表所示;当然,如果你愿意,也可以将 command >file 写作 command 1>file但这样做是多此一举。
- 当文件描述符为大于 1 的值时,比如 2就必须写上。
- 需要重点说明的是fd 和 >之间不能有空格,否则 Shell 会解析失败;> 和 file 之间的空格可有可无。为了保持一致,习惯在 > 两边都不加空格。
下面的语句是一个反面教材:
```bash
[root@wxin ~]# echo "c.biancheng.net" 1 >log.txt
```
注意 1 和 > 之间的空格。echo 命令的输出结果是 c.biancheng.net初衷是将输出结果重定向到 log.txt打开 log.txt 文件后,发现文件的内容为 c.biancheng.net 1这就是多余的空格导致的解析错误。也就是说Shell 将该条语句理解成了下面的形式:
```bash
[root@wxin ~]# echo "c.biancheng.net" 1 1>log.txt
```
**示例**
将 echo 命令的输出结果以追加的方式写入到 demo.txt 文件中。
```bash
[root@wxin ~]# echo $(date) >> demo.txt #将输入结果以追加的方式重定向到文件
[root@wxin ~]# cat demo.txt
Fri Feb 14 19:18:40 CST 2019
```
`ls -l`命令的输出结果重定向到文件中。
```bash
[root@wxin ~]# ls -l #先预览一下输出结果
total 4
-rw-------. 1 root root 1526 Mar 30 2019 anaconda-ks.cfg
[root@wxin ~]# ls -l >demo.txt #重定向
[c.biancheng.net]$ cat demo.txt #查看文件内容
total 4
-rw-------. 1 root root 1526 Mar 30 2019 anaconda-ks.cfg
```
**错误输出重定向示例**
命令正确执行是没有错误信息的,我们必须刻意地让命令执行出错,如下所示:
```bash
[root@wxin ~]# ls java #先预览一下错误信息
ls: cannot access java: No such file or directory
[root@wxin ~]# ls java 2>err.log #重定向
[root@wxin ~]# cat err.log #查看文件
ls: cannot access java: No such file or directory
```
**正确输出和错误信息同时保存**
```bash
[root@wxin ~]# ls -l >out.log 2>&1
[root@wxin ~]# ls java >>out.log 2>&1
[root@wxin ~]# cat out.log
total 8
-rw-------. 1 root root 1526 Mar 30 2019 anaconda-ks.cfg
-rw-r--r-- 1 root root 50 Feb 14 20:15 err.log
-rw-r--r-- 1 root root 0 Feb 14 20:15 out.log
ls: cannot access java: No such file or directory
```
- `out.log`的最后一行是错误信息,其它行都是正确的输出结果。
- 上面的实例将正确结果和错误信息都写入同一个文件中,建议把正确结果和错误信息分开保存到不同的文件中
```bash
[root@wxin ~]# ls -l >>out.log 2>>err.log
```
正确的输出结果会写入到`out.log`,而错误的信息则会写入到`err.log`
**`/dev/null`文件**
如果不想把命令的输出结果保存到文件,也不想把命令的输出结果显示到屏幕上,干扰命令的执行,可以把命令的所有结果重定向到`/dev/null`文件中
```bash
[root@wxin ~]# ls -l &>/dev/null
```
可以把`/dev/null`当成 Linux 系统的垃圾箱,任何放入垃圾箱的数据都会被丢弃,不能恢复。
#### 3. 输入重定向
输入重定向就是改变输入的方向,不再使用键盘作为命令输入的来源,而是使用文件作为命令的输入。
**示例:**
```bash
输入重定向例子:
if [ 5 -gt 3 ];then
cat >> ifcfg-eth2 <<-eof
TYPE=Ethernet
BOOTPROTO=none
NAME=ens160
DEVICE=ens160
ONBOOT=yes
IPADDR=192.168.26.200
PREFIX=24
GATEWAY=192.168.26.2
DNS1=192.168.26.2
eof
fi
```
**输入重定向举例**
统计文档中有多少行文字。
Linux wc 命令可以用来对文本进行统计,包括单词个数、行数、字节数,
```shell
wc [选项] [文件名]
选项:
-c # 选项统计字节数
-w # 选项统计单词数
-l # 选项统计行数
```
统计 readme.txt 文件中有多少行文本
```bash
[root@wxin ~]# vim readme.txt
www.wxin.oline
www.wxin.cn
www.wxin.eg
[root@wxin ~]# wc -l < readme.txt
3
```
逐行读取文件内容
```bash
#!/bin/bash
while read str; do
echo $str
done < readme.txt
while ls; do
echo hell
done
```
统计用户在终端输入的文本的行数。
用输入重定向符号 <<,这个符号的作用是使用特定的分界符作为命令输入的结束标志,而不使用 Ctrl+D 键。
```bash
[root@wxin ~]# wc -l <<END
> 123
> 789
> abc
> xyz
> END
4
```
wc 命令会一直等待用输入,直到遇见分界符 END 才结束读取。
<< 之后的分界符可以自由定义只要再碰到相同的分界符两个分界符之间的内容将作为命令的输入不包括分界符本身
**read 命令用法**
```shell
#!/bin/bash
stty -echo
read -p "输入密码:" password
echo
echo "我的密码是:$password"
stty echo
```
### 7. 管道
**管道`|`**
- 管道,从一头进去,从另一头出来。
- 在Shell中管道将一个程序的标准输出作为另一个程序的标准输入就像用一根管子将一个程序的输出连接到另一个程序的输入一样。
- 管道的符号是 |,下面的程序将 man 的标准输出作为 less 的标准输入,以实现翻页的功能:
```bash
[root@wxin ~]# man ls | less
```
**管道`tee`**
- 有时候我们想要同时将程序的输出显示在屏幕上(或进入管道)和保存到文件中,这个时候可以使用`tee`
- tee 程序的输出和它的输入一样,但是会将输入内容额外的保存到文件中:
```bash
[root@wxin ~]# cat /etc/passwd | tee hello.txt
```
tee 程序将 cat 程序的输出显示在屏幕上,并且在 hello.txt 文件中保留了副本。需要注意的是,如果 tee 命令中指定的文件已经存在,那么它将会被覆盖,使用 -a 选项在文件末尾追加内容(而不是覆盖)
```bash
[root@wxin ~]# cat hello.txt | tee -a hello.txt.bk
```
### 8. 命令排序
| 符号 | 说明 |
| ---- | ---------------------------------------------- |
| `;` | 无论前面是否执行成功,分号后的命令都会继续执行 |
| `&&` | 前面执行成功,后面的才继续执行 |
| `||` | 前面命令不成功,后面的命令也会继续 |
### 9. 通配符
**基础通配符**
| 通配符 | 说明 |
| :----: | :--------------------------------: |
| `*` | 匹配任意数量(包括零个)的任意字符 |
| `?` | 匹配单个任意字符 |
| `[]` | 匹配方括号内的任意**一个字符** |
| `[!]` | 匹配**不在**方括号内的字符 |
| `{}` | 匹配大括号内的任意一个字符串 |
**范围匹配**
| 模式 | 说明 |
| ---------- | ------------ |
| `[a-z]` | 匹配小写字母 |
| `[0-9]` | 匹配数字 |
| `[A-Za-z]` | 匹配所有字母 |