Shell

------ ## 一:Shell 概述 ### 1. shell 定义 ​ Shell 中文含义是“壳”;它是相对于内核来说的,因为它是建立在内核的基础上,面向用户的一种表现形式,比如我们看到一个球,见到的是它的壳,而非核。Linux中的Shell,是指一个面向用户的命令接口,表现形式就是一个可以由用户录入的界面,这个界面也可以反馈运行信息。 ​ Shell 是命令解释器,用于与操作系统交互,用来完成各种任务,如文件操作、系统管理、网络管理等。 ​ Shell 是一种程序设计语言,他有变量,有自己的语法结构等,shell程序设计语言可以编写功能很强、代码简短的程序 ### 2. Shell 在 Linux 中的存在形式 ​ 由于 Linux 不同于 Windows,Linux 是内核与界面分离的,它可以脱离图形界面而单独运行,同样也可以在内核的基础上运行图形化的桌面。 这样,在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系统默认使用的Shell,bash 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 的易用特点。许多安装脚本都使用 ksh,ksh 有42条内部命令,**与 bash 相比有一定的限制性**。 **TCsh:** ​ tcsh 是 csh 的增强版,与C Shell完全兼容。 **Sh:** ​ 是一个快捷方式,已经被`/bin/bash`所取代。 **Nologin:** ​ 指用户不能登录 **Zsh:** ​ 前 Linux 里最庞大的一种 zsh。它有84个内部命令,使用起来也比较复杂。一般情况下,不会使用该Shell。 ### 5. Shell 使用场景 - 自动化批量系统初始化程序 (update,软件安装,时区设置,安全策略...) - 自动化批量软件部署程序 (LAMP,LNMP,Tomcat,LVS,Nginx) - 应用管理程序 (KVM,集群管理扩容,MySQL,DELLR720批量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.sh,sh 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 Backward,PageUp C-f Forward,PageDown 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 < 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]` | 匹配所有字母 |