如何编写幂等的shell脚本
Posted Linux命令手册
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何编写幂等的shell脚本相关的知识,希望对你有一定的参考价值。
前言
我们在执行shell脚本时(其它编程语言也一样),经常会遇到脚本调用第二次或第几次后就不按预期效果执行,亦或者换台服务器压根就执行不了的情况,大多数原因在于我们写代码时考虑的不够周全。
先解释下幂等是什么意思:
幂等是一个学数与计算机学科的概念,在编程里幂等指的是程序执行N次都与第一次执行产生的影响相同,并且不会产生副作用。
良好的程序总是以幂等的方式编写,那么我们下面探讨下如何编写幂等的shell脚本?
创建空文件
touch命令默认是幂等的,这意味着你多次执行,它都不会产生任何副作用,但是请注意,touch命令会更新文件的修改时间,如果程序对文件修改时间有依赖,请谨慎使用touch命令。
创建目录
切记在脚本里勿直接使用mkdir命令,而应与-p选项一起使用,如果所创建的目录存在,-p选项会确保mkdir时不会出错。
创建符号链接
创建一个软链接时,我们通常使用下面命令
ln -s source target
但是我们再次调用该命令时,将会报错,为了使ln命令幂等,需要使用-f选项。-f选项会在创建软链接前先删除已有的软链接。另外在做目录软链接时需要加上-n选项,也是为了创建目录软链接时不会报错。所以为了安全起见,在脚本里使用ln命令创建软链接时,请始终使用下面方式。
ln -sfn source target
删除文件
在脚本里删除文件不建议用rm filename这样的写法,因为如果被删除的文件不存在,rm命令会报错,应该加上-f选项忽略不存在的文件。或者在删除前判断文件是否存在。
if [[ -f filename ]]; then
rm filename
fi
修改文件
有时我们会向现有文件添加新行,例如向rc.local里添加一行,如果使用下面写法,脚本多次调用就会多次追加,显然不符合我们的预期。
echo "/usr/sbin/nginx" /etc/rc.local
所以要加个grep做为判断,使追加语句幂等。
if ! grep -qF "/usr/sbin/nginx" /etc/rc.local; then
echo "/usr/sbin/nginx" >> /etc/rc.local
fi
检查文件或目录是否存在
在删除文件部分已经演示了怎么判断一个文件是否存在,另外还有种情况需要向文件里写入一行数据,而不是追加。尽管每次执行的效果相同,但是加上判断,可以减少IO开销,提高脚本执行效率。例如:
if [[ ! -f "/tmp/filename" ]]; then
echo "我是一行数据" > /tmp/filename
fi
这里用-f操作符举了个例子,if还可以检查是否是个目录或者检查是否有执行权限等等。
-b 检查是否是块设备
-c 检查是否是字符设备
-d 检查是否是目录
-e 检查文件是否存在
-f 检查文件是否存在,并且是一个普通文件。
-h 检查是否是符号链接
-r 检查是否可读
-w 检查是否可写
-x 检查是否有执行权限
上面例举了常用属性检查操作符,查看if能够检查哪些属性,可以执行
man test
注:if是不能检查文件属性的,其实用的是test,通常我们在写脚本时习惯使用"[[ ]]",上面之所以这么写,是为了缩短篇幅,不展开讲了,不要被我误导^_^。
格式化分区
脚本里有格式化分区语句,例如格式化成xfs格式,可以使用下面命令。
mkfs.xfs /dev/sdb1
如果再次执行脚本,分区将会再次被格式化,后果不敢想象,为了使脚本幂等,我们可以在格式化前添加blkid命令。
blkid /dev/sdb1 || mkfs.xfs /dev/sdb1
blkid会打印分区的属性,因此只有当blkid执行失败才会调用mkfs.xfs命令。
最后
上面这些技巧大多数我相信你都知道,但是我们在写代码时,很容易忽略它们,甚至不考虑去使用。从长远看来,编写幂等且有弹性的脚本总是利大于弊,我只是抛砖引玉,重要的是养成幂等编写代码的习惯。因此,以后编写shell脚本尝试去使用吧。
最后的最后
我正在攒钱生娃,如果本文对你有帮助麻烦帮忙分享转发,能小额赞赏就再好不过了。先谢谢!
好了,就这样。
推荐阅读
以上是关于如何编写幂等的shell脚本的主要内容,如果未能解决你的问题,请参考以下文章