当前位置: 首页 > 科技观察

教你编写健壮可靠的shell脚本!

时间:2023-03-20 20:46:51 科技观察

如果你抱着奔跑的心态写shell脚本,那是很舒服的,但如果你想写出健壮可靠的shell脚本,就没那么容易了。那么有没有实际的经验或者方法呢?检查语法的第一个也是最简单的方法是使用工具来检查脚本。这部分在《有了这个神器,再也不怕shell写不对了》已经介绍过了。它可以最大程度地发现shell脚本的存在如果你不知道语法错误,我建议你不要错过它。为了保证脚本的健壮性和可靠性,在某些特殊情况下需要保证脚本提前出现,避免漏网之鱼。让我们看看哪些技术有效。脚本失败时退出。可以在脚本开头设置如下:set-e例如:#!/bin/bashset-elp#这里运行会报错。问题:$./test.shlp:Error-nodefaultdestinationavailable。当然,这也有缺点。有时命令执行可能已经失败,而您仍希望它继续执行。可以临时加上||真的:#!/bin/bashset-elp||truedate不过个人觉得这样的设置不是特别好用,因为很多时候需要处理不同的错误情况,而这个只能要么遇到错误就退出,要么认为是正确的,导致无法进入异常分支。通过set+e设置回来:set-e#commandset+e#othercommand打印脚本执行过程调试阶段,你可能想知道整个过程中执行了哪些命令,每个命令具体执行了什么,可以使用如下执行方法:sh-xtest.sh或者和上面类似,在开头加上set-x//来源:公众号【编程珠玑】//作者:守望先生#!/bin/bashset-xif[$#-lt1]thenecho"nopara"elseecho"para1$1"fi执行,输出如下:+[0-le1]+echonoparanopara前面带+的内容是实际执行的命令,可以看到比较条件是什么,变量展开后具体是哪个分支变成了具体的内容就很清楚了。Displaysundefinedvariables该变量在shell中没有定义,它仍然可以使用,但它的结果可能不是你所期望的。例如://来源:公众号【编程珠玑】//作者:看守先生#!/bin/bashif["$var"="abc"]thenecho"notabc"elseecho"abc"fihereI想判断var的内容是不是abc。其实var并没有定义,只是这里使用的时候并没有报错。如果我们想早点发现这类问题,避免问题被复杂的脚本所掩盖,那么我们可以在开头添加:set-u再次运行时,会提示:test.sh:5:test.sh:num:parameternotset再想象一下,你本来想删除:rm-rf$dir/*当dir为空时,变成了什么?你有没有后背发凉的感觉?有时我们可能会在其中一条管道命令失败时执行这样一条命令:cattest.sh|grepif|cut-d';'-f2一行执行三个命令,如果我们希望其中一条失败,整个命令都会失败,避免后面执行无意义的命令,那么可以在开始的时候设置:set-opipefail没有设置,即使cattest.sh执行失败,下面的grep其实还是会继续执行,这可能会导致一些意想不到的情况。如果您不希望这种情况发生,那么此设置很有帮助。静态变量使用readonly通常我们会在脚本的开头定义一些静态变量:MY_PATH=/usr/bin为了避免不小心修改MY_PATH,可以这样:readonlyMY_PATH=/usr/bin这种情况下,一旦有都是后面尝试修改的命令,只会报错。#!/bin/bashreadonlyMY_PATH=/usr/binMY_PATH=/usr/local/bin尝试运行一下:$./test.shtest.sh:3:test.sh:MY_PATH:isreadonly看,给你提示!给变量Set一个可选的初始值。例如:name=${1:-shouwang}echo"${name}"这里让name为$1,为第一个参数,为空时让name为shouwang。执行多条命令,使用&&,例如:cmd0;cmd1;cmd1这里,如果cmd0失败,下面的命令仍然会执行,如果不想下面的命令执行,可以使用:cmd0&&cmd1&&cmd1使用函数脚本本身比较短,一旦脚本变长,不使用函数,就会导致脚本难以维护,可读性差。总结其实开头介绍的脚本检查工具已经很有效了,基本的错误都可以检查出来,而其他内容更侧重于脚本调试,不漏掉任何可能的错误。最后,首先推荐shellcheck工具。