
使用模板构建高效的 Bash 脚本
Bash 脚本模板允许您高效地自动化管理任务。本指南提供了一种结构化的方法来创建脚本。这个起点简化了未来脚本的创建,我们将以一些基本测试来结束,以确保它按预期运行。
在本系列的上一篇文章中,您创建了一个非常小的、单行的 Bash 脚本,并探讨了创建 shell 脚本的原因,以及为什么它们对于系统管理员来说是最有效的选择,而不是编译后的程序。
这一次,您将开始创建一个 Bash 脚本模板,该模板可以用作其他 Bash 脚本的起点。该模板最终将包含帮助功能、许可声明、几个简单的函数以及一些逻辑来处理这些选项以及可能基于此模板的脚本所需的其他选项。
为什么要创建模板?
与一般的自动化一样,创建模板背后的想法是成为“懒惰的系统管理员”。模板包含您希望在所有脚本中包含的基本组件。与将这些组件添加到每个新脚本相比,它可以节省时间,并且可以轻松启动新脚本。
虽然快速创建带有命令行 Bash 语句的可执行文件似乎更容易,但在长期来看,一个编写良好且注释完善的 Bash 程序,具有帮助功能和接受命令行选项的能力,会更有效。
要求
对于您做的每个项目,都应该始终创建一组要求。这包括脚本,即使它只是一个只有两到三个项目的简单列表。我见过许多项目因缺少或编写不良的要求而失败。不要让这种情况发生在您身上。
此 Bash 模板的要求非常简单
- 创建一个可以用作未来 Bash 编程项目起点的模板。
- 该模板应遵循标准的 Bash 编程实践。
- 它必须包括
- 一个标题部分,可用于描述程序的功能和变更日志
- 许可声明
- 一个函数部分
- 帮助函数
- 一个测试程序用户是否为 root 用户的函数
- 一种评估命令行选项的方法
基本结构
一个基本的 Bash 脚本有三个部分。Bash 没有办法来划分部分,但部分之间的界限是隐含的。
- 所有脚本都必须以 shebang (#!) 开头,并且这必须是任何 Bash 程序的第一行。
- 函数部分必须在 shebang 之后和程序主体之前开始。作为我记录一切需求的一部分,我在每个函数之前放置一个注释,简要描述其预期用途。我还包括函数内部的注释以进一步阐述。简短的程序可能不需要函数。
- 程序的主要部分在函数部分之后。这可以是一个简单的 Bash 语句,也可以是数千行代码。我的一个程序有 200 多行代码,不包括注释。同一个程序有 600 多行注释。
这就是全部——任何 Bash 程序的结构都只有三个部分。
前导注释
我总是添加比这更多的内容,原因有很多。首先,我在 shebang 之后立即添加几个注释部分。这些注释部分是可选的,但我发现它们非常有用。
第一个注释部分是程序名称和描述以及变更历史记录。我在 IBM 工作时学到了这种格式,它提供了一种记录程序长期开发以及应用于程序的任何修复的方法。这是记录您的程序的重要开始。
第二个注释部分是版权和许可声明。我使用 GPLv2,这似乎是根据 GPLv2 许可的程序的标准声明。如果您使用不同的开源许可证,这也没问题,但我建议在代码中添加明确的声明,以消除任何潜在的混淆。
脚本模板开始时看起来像这样。
#!/bin/bash
#######################################################################
# scriptTemplate #
# #
# Use this template as the beginning of a new program. Place a short #
# description of the script here. #
# #
# Change History #
# 11/11/2019 David Both Original code. #
# This is a template for creating new Bash #
# shell scripts. Add new history entries as #
# needed. #
# #
#######################################################################
# #
# Copyright (C) 2007, 2023 David Both #
# LinuxGeek46@both.org #
# #
# This program is free software; you can redistribute it and/or #
# modify it under the terms of the GNU General Public License as #
# published by the Free Software Foundation; either version 2 of the #
# License, or (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
# General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the Free Software #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #
# 02111-1307 USA #
#######################################################################
#######################################################################
echo "hello world!"
运行程序以验证它是否按预期工作。
添加帮助函数
即使是相当简单的 Bash 程序也应该具有某种帮助功能,即使它相当简陋。不经常使用或复杂性使得 Bash 脚本难以记住。内置的帮助函数可以解决这个问题。
它允许您查看这些内容,而无需检查代码本身。一个良好且完整的帮助功能也是程序文档的一部分。
关于函数
在 Bash 脚本中,函数是可重用的代码块,您可以通过名称在命令行执行它,类似于任何其他命令。这些函数在其他编程语言中也有时称为过程或子例程。
您可以通过名称调用 Bash 函数,就像任何其他命令一样,无论是在脚本中还是直接在命令行 (CLI) 中。当调用函数时,它的代码会执行,然后控制权返回到调用函数的位置,程序从那里继续。
函数的语法是
FunctionName(){program statements}
通过在 CLI 中创建一个简单的函数来探索这一点。(该函数存储在创建它的 shell 实例的 shell 环境中。)您将创建一个名为 hw 的函数,它代表 “hello world”。在 CLI 中输入以下代码并按 Enter。然后输入 hw,就像输入任何其他 shell 命令一样
$ hw(){ echo "Hi there kiddo"; }
$ hw
Hi there kiddo
让我们超越教科书式的 “Hello world”。使用 declare 工具列出您定义的函数。当您调用一个函数时,它会执行其代码,然后将控制权返回到调用它的位置,无论是命令行、脚本还是函数调用之后的下一个语句。
$ declare -f | less
<snip>
hw ()
{
echo "Hi there kiddo"
}
<snip>
删除该函数,因为您不再需要它了。
运行 unset 命令
$ unset -f hw ; hw
bash: hw: command not found
创建帮助函数
在编辑器中打开 hello 程序,并在版权声明之后和 echo “Hello world!” 语句之前将下面的帮助函数添加到 hello 程序代码中。此帮助函数将显示程序的简短描述、语法图以及可用选项的简短描述。添加对帮助函数的调用以测试它,并添加一些注释行,以在函数和程序的主要部分之间提供可视化分隔
#######################################################################
# Help #
#######################################################################
Help()
{
# Display Help
echo "Add description of the script functions here."
echo
echo "Syntax: scriptTemplate [-g|h|v|V]"
echo "options:"
echo "g Print the GPL license notification."
echo "h Print this Help."
echo "v Verbose mode."
echo "V Print software version and exit."
echo
}
#######################################################################
# Main program #
#######################################################################
Help
此帮助函数中描述的选项对于我编写的程序来说是典型的,尽管代码中还没有任何选项。
运行程序以测试它
$ ./hello
Add description of the script functions here.
Syntax: scriptTemplate [-g|h|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
Hello world!
$
目前,每次都会显示帮助消息。我们将添加逻辑,使其仅在命令行中使用 -h
选项时显示。
处理选项
Bash 脚本处理命令行选项(例如 -h)的能力可以增加一些强大的功能,以指导程序并修改其工作方式。在 -h 选项的情况下,您希望程序将帮助文本打印到终端会话,然后退出,而不运行程序的其余部分。可以使用 while 命令(请参阅 Bash 编程第 3 部分:循环 以了解有关 while 的更多信息)结合 getops 和 case 命令,将处理命令行输入的选项的能力添加到 Bash 脚本中。
getops 命令读取命令行中指定的任何选项,并创建这些选项的列表。在下面的代码中,while 命令通过为每个选项设置变量 $options 来循环遍历选项列表。case 语句用于依次评估每个选项,并执行相应节中的语句。while 语句将继续评估选项列表,直到所有选项都已处理完毕,或者遇到 exit 语句(该语句终止程序)。
务必删除 echo “Hello world!” 语句之前的帮助函数调用,以便程序的主体现在看起来像这样
#######################################################################
# Main program #
#######################################################################
# Process the input options. Add options as needed. #
#######################################################################
# Get the options
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
esac
done
echo "Hello world!"
请注意 -h 的 case 选项中 exit 语句末尾的双分号。这是添加到此 case 语句的每个选项所必需的,以分隔每个选项的结尾。
测试
现在进行测试:让我们尝试在没有选项的情况下运行程序(看看它是否打印 “Hello world!”),并使用各种选项看看它的响应。
$ ./hello
Hello world!
这可行,所以现在测试显示帮助文本的逻辑
$ ./hello -h
Add description of the script functions here.
Syntax: scriptTemplate [-g|h|t|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
这按预期工作,所以尝试一些测试,看看当您输入一些意外的选项时会发生什么
$ ./hello -x
Hello world!
$ ./hello -q
Hello world!
$ ./hello -lkjsahdf
Add description of the script functions here.
Syntax: scriptTemplate [-g|h|t|v|V]
options:
g Print the GPL license notification.
h Print this Help.
v Verbose mode.
V Print software version and exit.
$
程序只是忽略任何没有特定代码的选项,而不会生成任何错误。但是请注意最后一个条目(带有 -lkjsahdf 作为选项):因为选项列表中有一个 h,所以程序识别它并打印帮助文本。此测试表明,程序无法处理不正确的输入,也无法在检测到任何错误输入时终止程序。
要处理意外的选项,请向 case
语句添加最终的 case (\?
)。这将捕获任何先前未明确定义的选项。
试试这个
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
\?) # incorrect option
echo "Error: Invalid option"
exit;;
esac
done
再次使用与之前相同的选项测试程序,看看它现在是如何工作的。
总结
这个增强的脚本现在可以处理命令行选项并提供帮助函数。
您的 Bash 脚本现在看起来像这样
#!/usr/bin/bash
#######################################################################
# scriptTemplate #
# #
# Use this template as the beginning of a new program. Place a short #
# description of the script here. #
# #
# Change History #
# 11/11/2019 David Both Original code. #
# This is a template for creating new Bash #
# shell scripts. Add new history entries as #
# needed. #
# #
#######################################################################
# #
# Copyright (C) 2007, 2023 David Both #
# LinuxGeek46@both.org #
# #
# This program is free software; you can redistribute it and/or #
# modify it under the terms of the GNU General Public License as #
# published by the Free Software Foundation; either version 2 of the #
# License, or (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
# General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the Free Software #
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA #
# 02111-1307 USA #
#######################################################################
#######################################################################
#######################################################################
# Help #
#######################################################################
Help()
{
# Display Help
echo "Add description of the script functions here."
echo
echo "Syntax: scriptTemplate [-g|h|v|V]"
echo "options:"
echo "g Print the GPL license notification."
echo "h Print this Help."
echo "v Verbose mode."
echo "V Print software version and exit."
echo
}
#######################################################################
# Main program #
#######################################################################
# Process the input options. Add options as needed. #
#######################################################################
# Get the options
while getopts ":h" option; do
case $option in
h) # display Help
Help
exit;;
\?) # incorrect option
echo "Error: Invalid option"
exit;;
esac
done
echo "Hello world!"
在本系列的下一篇文章中,我们将更详细地探讨测试。
1 条评论
评论已关闭。