如何编写幂等的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 filenamefi


修改文件


有时我们会向现有文件添加新行,例如向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.localfi


检查文件或目录是否存在


在删除文件部分已经演示了怎么判断一个文件是否存在,另外还有种情况需要向文件里写入一行数据,而不是追加。尽管每次执行的效果相同,但是加上判断,可以减少IO开销,提高脚本执行效率。例如:

if [[ ! -f "/tmp/filename" ]]; then    echo "我是一行数据" > /tmp/filenamefi


这里用-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脚本的主要内容,如果未能解决你的问题,请参考以下文章

Shell脚本中$0$?$!等的意义

「如何设计」具备幂等性的服务

如何保证幂等?

关于高并发系统数据幂等的常用技术解决方案

幂等和非幂等的理解

代码片段:Shell脚本实现重复执行和多进程