Bourne Shell 脚本
在您与 UNIX 和 Linux 打交道的过程中,您可能需要在某个时候编写脚本来编辑关键的系统文件,例如 /etc/passwd 或 rc 启动脚本。无论是什么文件,如果您的脚本搞砸了它,您的机器都会因此受损。半心半意的脚本可能足以处理普通文件,但在这些情况下就行不通了。
考虑一下 root 密码。如果您需要在单台机器上修改 root 密码,使用 passwd 命令非常容易。但是,如果您需要在 50 台或更多机器上更改 root 密码,问题就会变得更加困难。虽然仍然可以手动完成,但这将非常耗时且容易出错。解决此问题的一种方法是使用 EX。
如果您在 Red Hat Linux 上查看 EX 的 man 页面,您将获得 vim 的 man 页面。这不是错误。EX 是熟悉的 vi 界面之下的引擎。如果您知道如何访问,vi 的所有强大功能都可以在您的脚本中使用。
让我们从一些简单的编辑开始,逐步了解 root 密码更改示例。
列表 1 显示了一个简单的多行文件。假设我们想要删除包含单词“three”的第一行。我们可以编写列表 2 中的简短脚本来轻松完成此操作。
对于任何编写过 shell 脚本的人来说,列表 2 中的第 1 行到第 6 行都应该很熟悉。如果您从未编写过脚本,我建议您阅读 Learning the bash Shell 这本书(请参阅“资源”)以入门。
第 5 行是开始有趣的地方。我们使用 -s 选项调用 EX,告诉 EX 以静默模式运行。我们要操作的文件在 $TARGET 变量中输入。EX 的无趣输出被重定向到 /dev/null,因为我们不希望它干扰脚本本身的任何输出。如果您想在调试期间查看此信息,可以删除 >/dev/null。<<E_O_F 标记着“Here”文件的开始。
Here 文件是一种将文件内容放置在脚本中的方法。<<E_O_F 后面的行是文件的第一行。Here 文件由直到以 E_O_F 开头的行之前的所有行组成。此标记(它结束 Here 文件)可以是任何唯一的字符组合。我们在这里使用 E_O_F 是一种约定。“<<”的作用是将 Here 文件的内容馈送到 EX,EX 使用这些命令来编辑 $TARGET 文件。请注意,Here 文件没有缩进。如果我们将 <<E_O_F 更改为 <<-E_O_F,添加“-”,我们可以使用 TAB 字符缩进 Here 文件。如果这些 TAB 字符由于某种原因变成了空格,可能是通过复制粘贴操作,Here 文件将停止工作,E_O_F 将永远不会被看到,并且您的脚本中 E_O_F 标记下面的内容将被馈送到 EX,从而产生不可预测的输出。因此,我个人制定了一项政策,永不缩进 Here 文件。有关 Here 文件的更多信息,请参阅 UNIX Power Tools 这本书(在“资源”中)。
Here 文件的第一行是第 6 行,其中包含 1。这会将 EX 中的行指针强制指向文件的第一行。虽然这对于脚本工作并非完全必要,但它确实消除了在编辑期间后续搜索从哪里开始的任何混淆。我发现这是一个有用的编程实践。
第 7 行是一个正则表达式。EX 使用此正则表达式搜索 $TARGET 文件,并将其行指针设置为包含单词“three”的第一行。在列表 1 中,这是第 3 行。第 10 行正则表达式中的尾随 “d” 告诉 EX 删除该行。第 8 行 vi 用户很熟悉。它的意思是写入、退出并且“不要与我争论”。第 9 行是 E_O_F 标记,它标记着 Here 文件的结尾。
我们可以使用 a 或 i 命令向文件中添加行。列表 3 显示了这些示例。请注意,尾随 “d” 已从正则表达式中消失。我们使用正则表达式来设置行指针,而不是删除行。a 命令在正则表达式中定义的行之后追加一行,而 i 命令在正则表达式中定义的行之前插入一行。. 命令告诉 EX 退出编辑模式,类似于在 vi 中按 ESC 键。列表 3 中的最后一个 EX 示例将 1 更改为 $,强制行指针指向文件末尾。然后我们追加一行,这与以下命令具有相同的效果
echo "This line is added at the bottom of the \ file." >> $TARGET
现在我们已经掌握了简单的编辑,让我们看看前面提到的更复杂的问题,即更改多个 root 密码。一旦我们使用 passwd 命令更改了一个密码,我们就可以将密码哈希从 /etc/shadow 复制并粘贴到脚本中的变量中。列表 4 包含该脚本。REPL_STRING 变量包含新的密码哈希。请注意,我们必须使用反斜杠转义 “$”、“.” 和 “/”,以防止 EX 将这些解释为特殊字符并给出不可预测的输出。如您所见,此脚本与之前的示例之间唯一的主要区别是正则表达式。
由于篇幅限制,我不会在此处完整解释正则表达式,只想说它的作用是“记住”现有密码字段每一侧的所有内容,并将其添加到 REPL_STRING 变量的每一侧,从而在 /etc/passwd 文件中构成一个新的 root 行。在脚本的末尾,我们使用 pwconv 将新的密码哈希放入 /etc/shadow 文件中。此脚本可以放在所有机器都可以挂载的位置,并且可以由每台机器远程执行,从而使它们都具有相同的 root 密码。
如您所见,EX 对脚本的文件编辑能力仅受您对正则表达式的了解程度的限制。如果您目前不使用正则表达式,那么非常值得花时间学习它们。有关正则表达式的更多信息,请阅读 Mastering Regular Expressions 这本书(请参阅“资源”)。
