摘要:从这一张开始,进入本书的最后一部分——编写shell脚本。之前的学习过程中我们一直一条命令一条命令的输入,这是交互式的。从本章开始,编写shell脚本,让shell自动地执行复杂的命令序列。

什么是shell脚本

shell 脚本就是一个包含一系列命令的文件。shell 读取这个文件,然后执行文件中的所有命令,就好像这些命令已经直接被输入到了命令行中一样。

shell不仅是命令行接口,还是脚本语言解释器。

怎样编写一个shell脚本

为了成功地创建和运行一个shell 脚本,我们需要做三件事情:

  1. 编写一个脚本。

    Shell 脚本就是普通的文本文件。所以我们需要一个文本编辑器来书写它们。

  2. 使脚本文件可执行。

    我们需要设置脚本文件的权限来允许其可执行。

  3. 把脚本放置到shell 能够找到的地方。

    当没有指定可执行文件明确的路径名时,shell 会自动地搜索某些目录,来查找此可执行文件。为了最大程度的方便,我们会把脚本放到这些目录当中。

脚本文件格式

下面让我们开始一个小例子。让我们启动vim,建个名为hello_world的文件,输入以下脚本并保存:

#!/bin/bash
# This is our first script
echo 'Hello World!'

第二行是一个注释;第三行是一句命令;那第一行呢?

#! 字符序列是一种特殊的结构叫做 shebang。这个 shebang 被用来告诉操作系统将执行此脚本所用的解释器的名字。每个 shell 脚本都应该把这一文本行作为它的第一行。

可执行权限

下一步我们要做的事情是让我们的脚本可执行。使用 chmod 命令,这很容易做到:

xuxg@xuxg-ubuntu:~$ ls -l hello_world
-rw-r--r-- 1 xuxg xuxg 59 Mar 30 17:27 hello_world
xuxg@xuxg-ubuntu:~$ chmod 755 hello_world
xuxg@xuxg-ubuntu:~$ ls -l hello_world
-rwxr-xr-x 1 xuxg xuxg 59 Mar 30 17:27 hello_world

对于脚本文件,有两个常见的权限设置;权限为 755 的脚本,则每个人都能执行,和权限为700 的脚本,只有文件所有者能够执行。注意为了能够执行脚本,脚本必须是可读的。

脚本文件位置

当设置了脚本权限之后,我们就能执行我们的脚本了:

xuxg@xuxg-ubuntu:~$ ./hello_world
Hello world!

为了能够运行此脚本,我们必须指定脚本文件明确的路径。如果我们没有那样做,我们会得到这样的提示:

xuxg@xuxg-ubuntu:~$ hello_world

Command 'hello_world' not found

为什么会这样呢?什么使我们的脚本不同于其它的程序?结果证明,什么也没有。我们的脚本没有问题。是脚本存储位置的问题。之前我们讨论了 PATH 环境变量及其在系统查找可执行程序方面的作用。回顾一下,如果没有给出可执行程序的明确路径名,那么系统每次都会搜索一系列的目录,来查找此可执行程序。这个/bin 目录就是其中一个系统会自动搜索的目录。这个目录列表被存储在一个名为 PATH 的环境变量中。这个 PATH 变量包含一个由冒号分隔开的目录列表。我们可以查看 PATH 的内容:

xuxg@xuxg-ubuntu:~$ echo $PATH
/home/xuxg/.local/bin:/usr/local/node/node-v12.16.1-linux-x64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

这里我们看到了我们的目录列表。如果我们的脚本位于此列表中任意目录下,那么我们的问题将会被解决。

我们可以在个人家目录下建个bin目录,然后让PATH变量包含这个自定义的目录。这样再把脚本文件放进bin目录,就可以直接通过脚本名来运行脚本,而不需要指定路径了。

注意:在 Ubuntu 系统中,如果存在 ∼/bin 目录,当执行用户的.bashrc 文件时,Ubuntu 会自动地添加这个 ∼/bin 目录到 PATH 变量中。所以在 Ubuntu 系统中,如果我们创建了这个∼/bin 目录,随后退出,然后再登录,一切会正常运行。

xuxg@xuxg-ubuntu:~$ mkdir bin
xuxg@xuxg-ubuntu:~$ mv hello_world bin

注销当前用户,重新登录之后,就可以直接用脚本名执行脚本而不需要指定路径了:

xuxg@xuxg-ubuntu:~$ hello_world
Hello world!

脚本文件的好去处

这个 ∼/bin 目录是存放为个人所用脚本的好地方。如果我们编写了一个脚本,系统中的每个用户都可以使用它,那么这个脚本的传统位置是 /usr/local/bin。系统管理员使用的脚本经常放到 /usr/local/sbin 目录下。大多数情况下,本地支持的软件,不管是脚本还是编译过的程序,都应该放到 /usr/local 目录下,而不是在 /bin 或 /usr/bin 目录下。这些目录都是由 Linux 文件系统层次结构标准指定,只包含由 Linux 发行商所提供和维护的文件。

更多的格式技巧

脚本书写的关键目标之一是为了易于维护;也就是说,一个脚本可以轻松地被作者或其它用户修改,使它适应变化的需求。使脚本容易阅读和理解是一种方便维护的方法。

长选项名称

许多命令的选项都有长短两种格式。为了减少输入,当在命令行中输入选项的时候,短选项更受欢迎,但是当书写脚本的时候,长选项能提供可读性。

缩进和行继续符

当使用长命令的时候,通过把命令在几个文本行中展开,可以提高命令的可读性。

通过使用行继续符(反斜杠-回车符序列)和缩进,可以使脚本更易读。

脚本和命令行的一个区别是,脚本可能使用 tab 字符来实现缩进,然而命令行却不能,因为tab 字符被用来激活自动补全功能。

为书写脚本配置 vim

vim 文本编辑器有许多许多的配置设置。有几个常见的选项能够有助于脚本书写:

  • :syntax on

    语法高亮。通过这个设置,当查看脚本的时候,不同的 shell 语法元素会以不同的颜色显示。

  • :set hlsearch

    高亮查找结果。比如说我们查找单词“echo”。通过设置这个选项,这个单词的每个实例会高亮显示。

  • :set tabstop=4

    设置一个 tab 字符所占据的列数。默认是 8 列。把这个值设置为 4(一种常见做法),从而让长文本行更容易适应屏幕。

  • :set autoindent

    打开 “auto indent” 功能。这导致 vim 能对新的文本行缩进与刚输入的文本行相同的列数。对于许多编程结构来说,这就加速了输入。停止缩进,输入 Ctrl-d。

通过把这些命令(没有开头的冒号字符)添加到你的 ∼/.vimrc 文件中,这些改动会永久生效。

总结归纳

在这脚本编写的第一章中,我们已经看过怎样编写脚本,怎样让它们在我们的系统中轻松地执行。我们也知道了怎样使用各种格式技巧来提高脚本的可读性(可维护性)。在以后的各章中,轻松维护会作为编写好脚本的中心法则一次又一次地出现。