没有哪种编程语言是完美的。甚至没有一种最佳语言;只有适合或可能不太适合特定用途的语言。 --赫伯特·梅耶 |
对于任何希望在系统管理方面达到相当熟练程度的人来说,即使他们不希望实际编写脚本,掌握 shell 脚本编程知识也是至关重要的。想想看,当 Linux 机器启动时,它会执行以下目录中的 shell 脚本:/etc/rc.d以恢复系统配置和设置服务。详细了解这些启动脚本对于分析系统行为以及可能修改系统至关重要。
脚本编写技巧并不难掌握,因为脚本可以分成小块构建,并且只有相当少量的 shell 特有运算符和选项 [1] 需要学习。语法很简单——甚至可以说是朴素——类似于在命令行调用和链接实用程序,并且只有少数 “规则” 控制它们的使用。大多数短脚本第一次就能正常工作,即使是较长的脚本,调试也很简单。
在 个人 计算 的 早期 ,BASIC 语言 使
任何 具有 相当 计算机 技能 的 人 都 能 在 早期
一代 微型计算机 上 编写 程序 。几十年 后 ,Bash 脚本
语言 使 任何 对 Linux 或 具有 基本 知识 的 人
UNIX 都 能 在 现代 机器 上 做 同样 的 事情 。
我们 现在 拥有 微型化 的 单板 计算机 ,具有 惊人 的
能力 ,例如 Raspberry Pi。
Bash 脚本 提供 了 一种 探索 这些 设备 能力 的 方法
迷人 的 设备 。
shell 脚本是一种快速而粗略的原型化复杂应用程序的方法。即使让有限的功能子集在脚本中工作,通常也是项目开发中有用的第一阶段。通过这种方式,可以测试和修改应用程序的结构,并在继续用 C、C++、Java、Perl 或 Python 进行最终编码之前,找到主要的缺陷。
shell 脚本编程可以追溯到经典的 UNIX 哲学,即将复杂的项目分解为更简单的子任务,将组件和实用程序链接在一起。许多人认为这是一种比使用新一代功能强大的多合一语言(如 Perl)更好,或者至少更美观的问题解决方法,这些语言试图成为所有人的所有事物,但代价是迫使您改变思维过程以适应工具。
根据 赫伯特·梅耶 的说法,“一种有用的语言需要数组、指针和构建数据结构的通用机制。” 按照这些标准,shell 脚本编程在某种程度上不足以成为 “有用” 的。或者,也许不是……
何时不使用 shell 脚本
如果以上任何一项适用,请考虑更强大的脚本语言——也许是 Perl、Tcl、Python、Ruby——或者可能是编译语言,例如 C、C++ 或 Java。即便如此,将应用程序原型化为 shell 脚本可能仍然是一个有用的开发步骤。 |
我们将使用 Bash,它是 [3] “Bourne-Again shell” 的首字母缩写,也是对 Stephen Bourne 现已成为经典的 Bourne shell 的双关语。 Bash 已成为大多数 UNIX 版本上 shell 脚本编程的 事实上的 标准。本书涵盖的大多数原则同样适用于使用其他 shell 进行脚本编程,例如 Korn Shell(Bash 从中派生出一些功能)[4] 以及 C Shell 及其变体。(请注意,由于 Tom Christiansen 在 1993 年 10 月的 Usenet 帖子 中指出的某些固有问题,不建议使用 C Shell 编程。)
接下来是关于 shell 脚本编程的教程。它大量依赖示例来说明 shell 的各种功能。示例脚本可以工作——它们已经过测试,尽可能地——其中一些甚至在现实生活中也很有用。读者可以使用源代码存档中示例的实际工作代码(scriptname.sh或scriptname.bash),[5] 给它们 执行 权限(chmod u+rx scriptname),然后运行它们以查看会发生什么。如果 源代码存档 不可用,则从 HTML 或 pdf 渲染版本中剪切并粘贴。请注意,此处介绍的一些脚本在解释之前就引入了功能,这可能需要读者暂时跳到前面以获得启发。
除非另有说明,否则本书的 作者 编写了以下示例脚本。
他的面容大胆而无畏。 --埃德蒙·斯宾塞 |
[1] | 这些被称为 内建命令,是 shell 内部的功能。 |
[2] | 虽然 递归 在 shell 脚本中是可能的,但它往往很慢,并且其实现通常是 丑陋的权宜之计。 |
[3] | 首字母缩略词 是通过将单词的首字母粘贴在一起形成令人绕口的短语而成的 人造 词。这种道德败坏且有害的做法应受到适当的严厉惩罚。公众鞭刑不失为一个建议。 |
[4] | ksh88 的许多功能,甚至一些来自更新的 ksh93 的功能已合并到 Bash 中。 |
[5] | 按照惯例,用户编写的符合 Bourne shell 规范的 shell 脚本通常采用带有.sh扩展名的名称。系统脚本,例如在/etc/rc.d中找到的那些,不一定符合此命名法。 |