Linux 管理员 – Shell 脚本
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 也受雇于贝尔实验室)
每个人都有自己喜欢的贝壳,每个人都有自己的长处和难点。但在大多数情况下,Bash 将成为所有 Linux 发行版和最常用的默认 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。
大多数像 Bash 这样的现代 shell 提供了允许更复杂的shell 脚本来自动化常见和复杂任务的构造。
构造包括 –
- 脚本流控制(ifthen 和 else)
- 逻辑比较运算(大于、小于、等于)
- 循环
- 变量
- 参数定义操作(类似于带命令的开关)
使用 Shell 脚本与脚本语言
在考虑执行任务时,管理员经常会问自己:我应该使用 shell 脚本还是脚本语言,如 Perl、Ruby 或 Python?
这里没有固定的规则。shell 与脚本语言之间只有典型的区别。
壳
Shell 允许在 Linux 操作系统上使用 Linux 命令,例如sed、grep、tee、cat和所有其他基于命令行的实用程序。事实上,几乎任何命令行 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主机命令周围使用了一个包装器。如果我们想做更多事情并让我们自己的应用程序像主机一样在 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 自动化任务的基本构建块开始。
输入输出和重定向
处理标准输出到另一个命令 –
[rdc@centos ~]$ cat ~/output.txt | wc -l 6039 [rdc@centos ~]$
上面,我们已经将cat’sstoud传递给wc进行管道字符处理。wc然后处理cat的输出,将 output.txt 的行数打印到终端。将管道字符视为从一个命令传递输出的“管道”,由下一个命令处理。
以下是处理命令重定向时要记住的关键概念 –
Number | 文件描述符 | 特点 |
---|---|---|
0 | 标准输入 | < |
1 | 标准输出 | > |
2 | 标准误 | |
附加标准输出 | >> | |
分配重定向 | & | |
管道标准输出到标准输入 | | |
我们在第一章中介绍了这一点,并没有真正谈论重定向或分配重定向。在 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 的示例 –
标准输出
[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 传递给文本文件时的一个注意事项是>>和>之间的区别。双“>>”将附加到文件,而单数形式将破坏文件并写入新内容(因此所有先前的数据都将丢失)。
标准输入
[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 位数字从包含 65535 中所有数字的文本文件传递给wc,并通过egrep过滤器。
使用 & 重定向输出
可以使用&字符重定向输出。如果我们想将 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 管理工具箱中的一个很好的工具。