Linux 管理员 - Shell 脚本
Bash Shell 简介
与 GNU Linux 的版本一样,shell 也有很多种,兼容性也各不相同。CentOS 中的默认 shell 称为 Bash 或 Bourne Again Shell。Bash shell 是 Stephen Bourne 开发的 Bourne Shell 的现代修改版本。Bash 是 Ken Thompson 和 Dennis Ritchie 在贝尔实验室开发的 Unix 操作系统上原始 Thompson Shell 的直接替代品(Stephen Bourne 也受雇于贝尔实验室)
每个人都有自己喜欢的 shell,每个 shell 都有自己的优点和缺点。但在大多数情况下,Bash 将成为所有 Linux 发行版的默认 shell,并且是最常用的 shell。有了经验,每个人都会想探索和使用最适合自己的 shell。但与此同时,每个人都希望掌握 Bash shell。
其他 Linux shell 包括:Tcsh、Csh、Ksh、Zsh 和 Fish。
对于 CentOS 管理员来说,掌握使用任何 Linux shell 的专家级技能非常重要。正如我们前面提到的,与 Windows 不同,Linux 的核心是命令行操作系统。shell 只是一个用户界面,允许管理员(或用户)向操作系统发出命令。如果 Linux 系统管理员是航空公司的飞行员,使用 shell 就像是将飞机从自动驾驶仪上取下,然后抓住手动控制,以实现更灵活的飞行。
Linux shell,如 Bash,在计算机科学术语中被称为命令行解释器。 Microsoft Windows 还有两个命令行解释器,分别称为 DOS(不要与原始 DOS 操作系统混淆)和 PowerShell。
大多数现代 shell(如 Bash)都提供构造,允许更复杂的 shell 脚本 自动执行常见和复杂任务。
构造包括 −
- 脚本流控制(ifthen 和 else)
- 逻辑比较操作(大于、小于、相等)
- 循环
- 变量
- 定义操作的参数(类似于命令中的开关)
使用 Shell 脚本与脚本语言
管理员在考虑执行任务时经常会问自己:我应该使用 shell 脚本还是脚本语言(如 Perl、Ruby 或Python?
这里没有固定的规则。shell 与脚本语言之间只有典型的差异。
Shell
Shell 允许使用 Linux 命令,例如 sed、grep、tee、cat 以及 Linux 操作系统上所有其他基于命令行的实用程序。事实上,几乎任何命令行 Linux 实用程序都可以在您的 shell 中编写脚本。
使用 shell 的一个很好的例子是快速脚本来检查主机列表以进行 DNS 解析。
我们简单的 Bash 脚本用于检查 DNS 名称 −
#!/bin/bash for name in $(cat $1); do host $name.$2 | grep "has address" done exit
用于测试 DNS 解析的小单词列表 −
dns www test dev mail rdp remote
针对 google.com 域名的输出 −
[rdc@centos ~]$ ./dns-check.sh dns-names.txt google.com -doing dns dns.google.com has address 172.217.6.46 -doing www www.google.com has address 172.217.6.36 -doing test -doing dev -doing mail googlemail.l.google.com has address 172.217.6.37 -doing rdp -doing remote [rdc@centos ~]$
利用 shell 中的简单 Linux 命令,我们能够编写一个简单的 5 行脚本来从单词列表中审核 DNS 名称。即使使用实现良好的 DNS 库,在 Perl、Python 或 Ruby 中,这也会花费相当多的时间。
脚本语言
脚本语言将在 shell 之外提供更多控制。上面的 Bash 脚本使用了 Linux host 命令的包装器。如果我们想做更多事情并让我们自己的应用程序(如 host)在 shell 之外进行交互,该怎么办?这就是我们使用脚本语言的地方。
此外,有了高度维护的脚本语言,我们知道我们的操作在大多数情况下将适用于不同的系统。例如,Python 3.5 可以在任何其他运行 Python 3.5 并安装了相同库的系统上运行。如果我们想在 Linux 和 HP-UX 上运行 BASH 脚本,情况就不一样了。
有时,脚本语言和强大的 shell 之间的界限可能会很模糊。可以使用 Python、Perl 或 Ruby 自动执行 CentOS Linux 管理任务。这样做其实很常见。此外,富裕的 shell 脚本开发人员已经用 Bash 制作了一个简单但功能齐全的 Web 服务器守护进程。
凭借脚本语言和 shell 中任务自动化的经验,CentOS 管理员将能够在需要解决问题时快速确定从哪里开始。使用 shell 脚本启动项目是很常见的。然后随着项目变得越来越复杂,再进展到脚本(或编译)语言。
此外,可以对项目的不同部分同时使用脚本语言和 shell 脚本。一个例子可以是使用 Perl 脚本来抓取网站。然后,使用 shell 脚本通过 sed、awk 和 egrep 进行解析和格式化。最后,使用 PHP 脚本通过 Web GUI 将格式化的数据插入 MySQL 数据库。
了解了一些 shell 理论后,让我们开始使用基本构建块来自动执行 CentOS 中 Bash shell 的任务。
输入输出和重定向
将 stdout 处理为另一个命令 −
[rdc@centos ~]$ cat ~/output.txt | wc -l 6039 [rdc@centos ~]$
上面,我们已将 cat'sstoud 传递给 wc 以使用 管道 字符进行处理。 wc 然后处理 cat 的输出,将 output.txt 的行数打印到终端。将 pipe 字符视为传递一个命令的输出以供下一个命令处理的"管道"。
以下是处理命令重定向时要记住的关键概念 −
数字 | 文件描述符 | 字符 |
---|---|---|
0 | 标准输入 | < |
1 | 标准输出 | > |
2 | 标准错误 | |
附加 stdout | >> | |
分配重定向 | & | |
将 stdout 管道化为 stdin | | |
我们在第一章中介绍了这一点,但并没有真正谈论重定向或分配重定向。在 Linux 中打开终端时,您的 shell 被视为 −
- 标准输入 < 0
- 标准输出 > 1
- 标准错误 2
让我们看看它是如何工作的 −
[rdc@centos ~]$ lsof -ap $BASHPID -d 0,1,2 COMMAND PID USER **FD** TYPE DEVICE SIZE/OFF NODE NAME bash 13684 rdc **0u** CHR 136,0 0t0 3 /dev/pts/0 bash 13684 rdc **1u** CHR 136,0 0t0 3 /dev/pts/0 bash 13684 rdc **2u** CHR 136,0 0t0 3 /dev/pts/0 [rdc@centos ~]$
/dev/pts/0 是我们的伪终端。CentOS Linux 会查看它,并将我们的开放终端应用程序视为一个真正的终端,键盘和显示器通过串行接口插入。但是,就像虚拟机管理程序将硬件抽象为操作系统一样,/dev/pts 将我们的终端抽象为应用程序。
从上面的 lsof 命令中,我们可以在 FD 列下看到所有三个文件描述符都设置为我们的虚拟终端 (0,1,2)。我们现在可以发送命令,查看命令输出以及与命令相关的任何错误。
以下是 STDIN 和 STDOUT 的示例 −
STDOUT
[root@centosLocal centos]# echo "I am coming from Standard output or STDOUT." > output.txt && cat output.txt I am coming from Standard output or STDOUT. [root@centosLocal centos]#
也可以将 stdout 和 stderr 发送到单独的文件 −
bash-3.2# find / -name passwd 1> good.txt 2> err.txt bash-3.2# cat good.txt /etc/pam.d/passwd /etc/passwd bash-3.2# cat err.txt find: /dev/fd/3: Not a directory find: /dev/fd/4: Not a directory bash-3.2#
在搜索整个文件系统时,遇到了两个错误。每个错误都被发送到一个单独的文件以供稍后查看,而返回的结果则被放入一个单独的文本文件中。
在执行向终端输出大量数据的操作(如编译应用程序)时,将 stderr 发送到文本文件非常有用。这将允许查看可能从终端回滚历史记录中丢失的错误。
将 STDOUT 传递给文本文件时需要注意的一点是 >> 和 > 之间的区别。双">>"将附加到文件,而单数形式将破坏文件并写入新内容(因此所有以前的数据都将丢失)。
STDIN
[root@centosLocal centos]# cat < stdin.txt Hello, I am being read form Standard input, STDIN. [root@centosLocal centos]#
在上面的命令中,文本文件 stdin.txt 被重定向到 cat 命令,该命令将其内容回显到 STDOUT。
管道符"|"
管道符将获取第一个命令的输出,将其作为输入传递给下一个命令,允许第二个命令对输出执行操作。
现在,让我们将 cat 的标准输出"管道"到另一个命令 −
[root@centosLocal centos]# cat output.txt | wc -l 2 [root@centosLocal centos]#
上面,wc 对从管道传递过来的 cat 的输出执行计算。管道命令在过滤 grep 或 egrep 的输出时特别有用 −
[root@centosLocal centos]# egrep "^[0-9]{4}$" /usr/dicts/nums | wc -l 9000 [root@centosLocal centos]#
在上面的命令中,我们将文本文件中的每 4 位数字传递给 wc,该文本文件包含通过 egrep 过滤器传递的 65535 中的所有数字。
使用 & 重定向输出
可以使用 & 字符重定向输出。如果我们想将 STDOUT 和 STDERR 的输出直接放到同一个文件中,可以按如下方式实现 −
[root@centosLocal centos]# find / -name passwd > out.txt 2>&1 [root@centosLocal centos]# cat out.txt find: /dev/fd/3: Not a directory find: /dev/fd/4: Not a directory /etc/passwd [root@centosLocal centos]#
使用 & 字符进行重定向的工作方式如下:首先,将输出重定向到 out.txt。其次,STDERR 或文件描述符 2 被重新分配到与 STDOUT 相同的位置,在本例中为 out.txt。
重定向非常有用,在解决操作大型文本文件、编译源代码、在 shell 脚本中重定向输出以及发出复杂的 Linux 命令时出现的问题时非常有用。
虽然重定向功能强大,但对于较新的 CentOS 管理员来说可能会很复杂。练习、研究和偶尔向 Linux 论坛(例如 Stack Overflow Linux)提问将有助于解决高级解决方案。
Bash Shell 构造
现在我们对 Bash shell 的工作原理有了很好的了解,让我们学习一些常用来编写脚本的基本构造。在本节中,我们将探索 −
BASH 故障排除提示
与专用脚本语言相比,BASH 可能有点棘手。BASH 脚本中最大的一些问题来自于传递给 shell 的脚本操作错误转义或未转义。如果您查看了几次脚本,发现它没有按预期工作,请不要担心。即使是那些每天使用 BASH 创建复杂脚本的人,这种情况也很常见。
快速搜索 Google 或在专家 Linux 论坛上注册以提出问题,将很快得到解决。很有可能有人遇到过同样的问题,并且已经解决了。
BASH 脚本是一种快速创建强大脚本的好方法,可用于从自动化管理任务到创建有用的工具等所有方面。成为专家级 BASH 脚本开发人员需要时间和实践。因此,尽可能使用 BASH 脚本,它是您 CentOS 管理工具箱中必备的好工具。
linux_admin_shell_scripting.html