我是一名懒惰的DevOps工程师。 因此,每当我遇到同一任务两次以上时,我都会自动执行该任务。 尽管现在我们有许多自动化工具,但是自动化中首先想到的是bash或shell脚本。
在犯了很多错误和凌乱的脚本:)之后,我分享了我写一个好的shell脚本的经验,该脚本不仅看起来不错,而且可以减少出错的机会。
- 最小的修改费用。
- 您的程序应该自己说话,所以您不必解释它。
- 可重用性,当然,我不能一次又一次地编写相同类型的脚本或程序。
我坚信边做边学。 因此,让我们为自己创建一个问题陈述,然后尝试使用具有最佳实践的shell脚本来解决问题:)。 我想在此博客的评论部分中找到解决方案。
问题陈述
根据参数编写一个shell脚本来安装和卸载package(vim)。 该脚本应告诉软件包是否已安装。 如果未传递任何参数,则应打印帮助页面。
因此,在不浪费时间的情况下,让我们开始编写出色的shell脚本。 这是编写Shell脚本时应始终注意的事项列表。
脚本寿命
如果您的脚本是过程性的(每个后续步骤都依赖于上一步来完成),请帮帮忙 ,并在脚本开始处添加set -e ,以使脚本在第一个错误时存在。 例如:
#!/bin/bash
set -e # Script exists on first failure
set -x # For debugging purpose
install_package () {
yum install docker
}
list_docker_images () {
docker images # depends on success of install_package function
}
功能
啊哈,函数是我最喜欢的编程部分。 有句话
任何傻瓜都可以编写计算机可以理解的代码。 好的程序员编写人类可以理解的代码。 ”
为此,请始终尝试使用功能并正确命名它们,以便任何人都可以通过阅读其名称来理解该功能。 函数还提供了可重用性的概念。 它还消除了重复的代码,怎么办? 让我们看看这个
#!/bin/bash
install_package () {
local PACKAGE_NAME= " $1 "
yum install " ${PACKAGE_NAME} " -y
}
install_package "vim"
命令健全
通常,脚本会调用其他脚本或二进制文件。 当我们处理命令时,命令可能不会在所有系统上都可用。 所以我的建议是在继续之前检查它们。
#!/bin/bash
check_package () {
local PACKAGE_NAME= " $1 "
if ! command -v " ${PACKAGE_NAME} " > /dev/null 2>&1
then
printf " ${PACKAGE_NAME} is not installed.\n"
else
printf " ${PACKAGE_NAME} is already installed.\n"
fi
}
check_package "vim"
帮助页面
如果您熟悉Linux,您肯定会注意到每个Linux命令都有其帮助页面。 对于脚本来说同样如此。 包括--help标志将非常有帮助。
#!/bin/bash
INITIAL_PARAMS= "$*"
help_function () {
{
printf "Usage:- ./script <option>\n"
printf "Options:\n"
printf " -a ==> Install all base softwares\n"
printf " -r ==> Remove base softwares\n"
}
}
arg_checker () {
if [ " ${INITIAL_PARAMS} " == "--help" ]; then
help_function
fi
}
arg_checker
记录中
无论是开发人员,系统管理员还是DevOps,日志记录对于每个人来说都是最关键的事情。 没有日志,调试似乎是不可能的。 众所周知,大多数应用程序会生成日志以了解应用程序正在发生的情况,因此对于Shell脚本也可以实施相同的做法。 为了生成日志,我们有一个称为logger的bash实用程序。
#!/bin/bash
DATE=$(date)
declare DATE
check_file () {
local FILENAME= " $1 "
if ! ls " ${FILENAME} " > /dev/null 2>&1
then
logger -s " ${DATE} : ${FILENAME} doesn't exists"
else
logger -s " ${DATE} : ${FILENAME} found successfuly"
fi
}
check_file "/etc/passwd"
变数
我喜欢用下划线将我的变量命名为大写字母,这样,我不会与函数名和变量名混淆。 永远不要给a,b,c等作为变量名,而要像函数一样给变量取一个正确的名字。
#!/bin/bash
# Use declare for declaring global variables
declare GLOBAL_MESSAGE= "Hey, I am a global message"
# Use local for declaring local variables inside the function
message_print () {
local LOCAL_MESSAGE= "Hey, I am a local meesage"
printf "Global Message:- ${GLOBAL_MESSAGE} \n"
printf "Local Message:- ${LOCAL_MESSAGE} \n"
}
message_print
案例
案例也是shell脚本的一个有趣的部分。 但是问题是什么时候使用呢? 根据我的说法,如果您的Shell程序基于参数提供了多个功能,那么您应该进行案例分析。 例如:-如果您的Shell实用程序提供了安装和卸载软件的功能。
#!/bin/bash
print_message () {
MESSAGE= " $1 "
echo " ${MESSAGE} "
}
case " $1 " in
-i|--input)
print_message "Input Message"
;;
-o|--output)
print_message "Output Message"
;;
--debug)
print_message "Debug Message"
;;
*)
print_message "Wront Input"
;;
esac
在此博客中,我们介绍了函数,变量,脚本的寿命,日志记录,帮助页面和命令的完整性。
我希望这些主题在使用Shell脚本时对您的日常生活有所帮助。 如果您有任何反馈意见,请通过评论告知我。