第24章:编写第一个脚本
在前面几章中,我们已经组织起了一个命令行工具的兵器库。这些工具可以解决很多类型的计算问题,不过我们还是仅限于手动使用它们、一个个的在命令行中解决问题。如果能用 shell 做更多的工作,不是更伟大吗?答案是可以的。通过将这些工具结合进我们自己设计的程序中,shell 可以自动执行复杂序列的任务。我们可以写一个 shell 脚本(shell scripts)来实现它。
什么是 Shell 脚本?
最简单地说,一个 shell 脚本是包含一系列命令的文件。shell 读取这个文件并执行命令,如同它们是直接被输入在命令行上一样。
shell 是有点特别的,它既是一款强大的面对系统的命令行界面,同时还是一款脚本语言解释器。我们将会看到,大多数能在命令行上解决的问题,同样也能用脚本解决,反之亦然。
我们已经学习了许多 shell 特性,但是仅仅是聚焦于直接使用命令行。shell 还提供一组特性,通常是(但不是总是)供写程序时使用。
怎样编写 Shell 脚本
要成功地创建并运行一个 shell 脚本,我们需要做三件事。
写一个脚本。shell 脚本是普通的文本文件。所以我们需要一个文本编辑器。最好的文本编辑器都会提供句法高亮(syntax highlighting,),让我们看到脚本元素的彩色视图。句法高亮能帮助我们识别某些类型的常见错误。
vim
、gedit
、kate
等很多编辑器都是写脚本的上佳选择。使该脚本可执行。系统很挑剔,不会允许把任何文本文件当作一个程序看待,而且有很好的理由这么做!我们需要设置脚本文件的权限,使其可执行。
把脚本放在 shell 可以找到它的地方。对于可执行文件,shell 在没有明确指定路径名时,会自动搜索某些目录。为了方便,需要将我们的脚本放在这些目录里。
脚本文件的格式
为了保持编程传统,我们将创建一个 "Hello World" 的程序来演示一个最简单的脚本。来启动文本编辑器,键入下面的脚本:
最后一行脚本相当熟悉;它只是一条 echo
命令和一个字符串参数。第二行也很熟悉。它看起来像是注释,我们已经在许多配置文件中检查并编辑过。还有一点,在 shell 脚本中的注释可以出现在一行的末尾,假定注释前至少有一个空白字符,像这样:
行内从 #
符号之后的所有字符都会被忽略。
和许多事物一样,这个规则在命令行中也是奏效的:
尽管注释在命令行中的作用微乎其微,但还是奏效的。
脚本的第一行有点神秘。看起来它应该是注释,因为它开头是个 #
,但是看起来目的性很强。#!
字符串序列,实际上是一个特殊结构,叫做 shebang。它用来告诉内核应该用于执行后面脚本的解释器的名称。每个脚本都会将其作为第一行。
来将我们的脚本保存为 hello_world
。
可执行权限
下一步,我们必须使脚本可执行。用 chmod
能轻易做到。
对于脚本文件有两组常见的许可设置:755
则所有人都可以执行,700
则仅供属主使用。注意脚本必须是可读可执行。
脚本文件的位置
权限设置好后,我们已经可以执行脚本了:
为了让脚本运行,我们必须在脚本名前加一个明确的路径。如果没有,会得到:
为何如此?是什么导致我们的脚本和其它程序不一样?事实证明,没有什么不一样。我们的脚本是好的。它的路径有问题。在第 11 章中,我们讨论过 PATH
环境变量及其对系统如何搜索可执行程序的影响。回顾一下,如果没有明确指定路径,系统每次会检索一系列目录去找到一个可执行程序。这就是为何我们在命令行上输入 ls
后,系统知道去执行 /bin/ls
。/bin
目录是系统自动检索的目录之一。目录列表掌握在一个名为 PATH
的系统变量中。PATH
变量包含了一个冒号分隔符的可被检索的目录列表。我们可以看一下 PATH
的内容。
这里我们看到了目录列表。如果我们的脚本放置在列表中的任意一个目录中,问题就解决了。注意列表的第一个目录 /home/me/bin
。大多数 Linux 发行版会在 PATH
变量中包含一个用户家目录中的 bin
目录以允许用户执行自己的程序。所以,如果我们创建一个 bin
目录并将脚本放入其中,它就可以像其它程序一样工作了。
果然如此。
如果 PATH
变量不包含该目录,我们可以简单地将其加入 .bashrc
文件中的那一行中:
变更完之后,它会影响每一个新的终端会话。要想将变更应用到当前终端会话,就必须让 shell 重新读取 .bashrc
文件。可以通过 "sourcing" 完成。
点命令(.
)是 source
命令的同义词,是 shell 内建命令,它读取指定的 shell 命令文件并将其视为来自键盘的输入。
注意:Ubuntu(和大多数 Debian 系的发行版)中,如果当执行用户的
.bashrc
文件时,~/bin
目录已经存在,则系统会自动将~/bin
目录添加到PATH
变量中。所以,在 Ubuntu 系统中,如果我们创建了~/bin
目录然后登出再登录,所有的事情就都完成了。
对脚本文件而言的好位置
~/bin
目录是一个放置供个人用的脚本的好地方。如果我们写一个脚本,允许系统上所有的用户都能使用,则传统的位置是 /usr/local/bin
。供系统管理员用的脚本,则常放在 /usr/local/sbin
。在大多数情况下,本地提供的软件,无论脚本还是编译的程序,应该被放置在 /usr/local
层,而不应该在 /bin
或 usr/bin
中。这些目录是由 Linux 文件系统层次结构标准所指定,仅用于存放由 Linux 发行者提供并维护的文件的。
更多的格式化技巧
严肃的脚本编写有一个很重要的目标,就是易于维护(maintenance),即,一个脚本可以被其作者或其他人轻松修改以适应变更过的需求。使一个脚本易于被阅读和理解,是促进易于维护的一个方法。
长选项名
许多我们学过的命令同时支持短选项名和长选项名。例如,ls
命令有很多选项,既可以用短形式,也可以用长形式。例如:
等价于:
出于减少键入的原因,短选项在命令行中更受欢迎,但是当写脚本时,长选项更便于阅读。
缩进和续行
当使用长命令时,可以将命令分割在几行内来改善可读性。第 17 章中,我们看到特别长的一个 find
命令。
显然,这条命令初看之下很难识别。在脚本中,如果写成这样,可以更容易理解:
使用续行(反斜杠-换行序列)和缩进,这条复杂命令的逻辑对于读者来说就能更清晰地得到描述。该技术在命令行中也有效,尽管因为很难写、很难修改而很少用。脚本和命令行之间的一个区别是,脚本可以使用制表符来完成缩进,而命令行则不能,因为在命令行中,制表符用来补全命令了。
为编写脚本配置
vim
vim
文本编辑器有许许多多的配置设置。有一些常见的选项可以为编写脚本提供便利。下面的命令会打开句法高亮:
:syntax on
通过这个设置,当查看一个脚本时,shell 句法的不同元素会用不同的颜色显示。这有助于识别某些类型的程序错误。看起来也很酷。注意,要使这些特性起作用,必须安装完整版的
vim
,并且保证正在编辑的文件必须有 shebang 以指示文件是一份 shell 脚本。如果在使用上面这条命令时有困难,试着用:set syntax=sh
替代。下面这条命令打开了高亮搜索结果的选项。
:set hlsearch
如果要检索一个单词
echo
。因为打开了这个选项,这个单词的每个实例都会被高亮显示。下面这个设置设置一个制表符占几个字符栏宽:
:set tabstop=4
默认值是八栏。设置值是 4(这是实际操作中常见的),使得较长的行更易于适应屏幕。
下面的设置打开了「自动缩进」功能:
:set autoindent
这使得
vim
将新起的一行的缩进量与刚刚键入过的一行持平。这能加快在许多类型的编程结构中的编辑速度。要取消缩进,请按Ctrl-d
。这些变更会在
~/.vimrc
文件中保存这些命令(没有前置冒号),使得这些变更永久有效。
总结
在编写脚本的第一章中,我们学习了如何写脚本,如何更方便在系统中执行脚本。还学习了使用不同的格式以增进脚本的可读性(也因此更易维护)。接下来的章节中,会反复遇到易于维护这个在良好的脚本编写中的中心原则。
扩展阅读
Last updated
Was this helpful?