本文转载自微信公众号《编程珠玑》,作者王寿老师。转载本文请联系编程诸暨公众号。抱着能跑多久就跑多久的心态写shell脚本是很舒服的,但是想要写出健壮可靠的shell脚本,就没那么容易了。那么有没有实际的经验或者方法呢?检查语法的第一个也是最简单的方法是使用工具来检查脚本。这部分已经在《有了这个神器,再也不怕shell写不对了》介绍过。它可以发现的存在如果你不知道语法错误,我建议你不要错过它。为了保证脚本的健壮性和可靠性,在某些特殊情况下需要保证脚本提前出现,避免漏网之鱼。让我们看看哪些技术有效。脚本失败时退出可在脚本开头设置如下:set-e例如:#!/bin/bashset-elp#这里会运行errordate这种情况下,一旦运行出错,就会退出。不要放过一个问题:$./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"fi本来是想判断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工具。地址:https://www.shellcheck.net作者:守望,linux应用开发者,目前在公众号【编程明珠】分享Linux/C/C++/数据结构与算法/工具等原创技术文章和学习资源?.原文链接:https://mp.weixin.qq.com/s/EpCoiHHpCdPcj8kkeRjHjw
