小K本着“能坐着绝不站着,能躺着绝不坐着”的“懒人之道”,努力打造规范和可靠的代码。下面就给大家讲讲小k在学习和使用shell过程中遇到的问题。
0x00 前言
小K本着“能坐着绝不站着,能躺着绝不坐着”的“懒人之道”,努力打造规范和可靠的代码。下面就给大家讲讲小k在学习和使用shell过程中遇到的问题。
0x01 指令异常判断
今天真高兴啊,今天真兴高,小K一个小时就完成了今天的代码开发。小Q,来给我测试一下,马上就能上线。
<code>#!/bin/bash echo '先将原数据文件a.txt做个备份' cp a.txt bak.txt echo '将原文件里的xx替换成yy' sed -i "s/xxx/yyy/g" a.txt ###balabala省略一堆指令 echo '成功'/<code>
小Q:嘿嘿,来啦。不管三七二十一,先来个异常场景:a.txt不存在。
执行日志如下:
<code>先将原数据文件a.txt做个备份 cp: a.txt: No such file or directory 将原文件里的xx替换成yy sed: 1: "a.txt": command a expects \ followed by text 成功/<code>
小Q:小K啊,代码都报异常了,最后告诉我成功。。。
小K:简单,我通过$?的值来判断上一步的状态进而决定是继续执行还是异常退出。(哼哼,为了防止小Q在找茬儿,我每个都加判断)
<code>echo '先将原数据文件a.txt做个备份' cp a.txt bak.txt if [ $? -ne 0 ];then echo 'command fail' exit 1 fi echo '将原文件里的xx替换成yy' sed -i "s/xxx/yyy/g" a.txt if [ $? -ne 0 ];then echo 'command fail' exit 1 fi ###balabala一堆逻辑代码 echo '成功'/<code>
一顿操作猛如虎,原来10行的代码活生生变成了40行,有没有简单的方式呢?(幸亏公司不是拿代码行数做KPI,要不然我能写到公司破产)
那有什么方式可以优化一下呢?噔噔噔噔...答案就是:set -o errexit
<code>set -o errexit echo '先将原数据文件a.txt做个备份' cp a.txt bak.txt echo '将原文件里的xx替换成yy' sed -i "s/xxx/yyy/g" a.txt ###balabala一堆逻辑代码 echo '成功'/<code>
Tips:
- 一旦有任何一个指令返回非0值,则异常退出,此时$?将不起作用
- 如果需要程序出错也继续执行,可以在执行命令前加if判断或者在命令上追加“ || true”
0x02 函数化
小K作为努力“粪”发向上的有为“青年”,把日志打成这样实在是让人看不下去,至少得加个时间戳吧。
这个不难,通过date就行,但这一行一行的替换着实不像我这个懒人的风格。
马上中午了,被小Q折腾的连水都没喝一口,直接上代码:
<code>#具体格式可以自行定义,这里以 时间 日志级别 日志信息展示 function logger() { echo $(date "+%Y-%m-%d %H:%M:%S")" $1:$2" } logger 'info' '先将原数据文件a.txt做个备份' cp a.txt bak.txt/<code>
Tips:
- 公用代码,业务逻辑都可以封装到函数。简单明了,可读性强。
0x03 参数传递
小P:小K,小Q来一下。我突然想到原数据文件可能不叫a.txt,我又不想改文件名。你们给搞下。
小K:(又改需求,一脸黑线。。。) 那我加个外部参数传递吧: sh xxx.sh a.txt
<code>source=$1 logger 'info' "先将原数据文件[${source}]做个备份" cp ${source} bak.txt/<code>
小Q:如果后面还要加功能,需要传入多个参数呢?
小K:嗯。。。使用$1的方式,代码里肯定还得需要定义多个变量,有点刷代码行数的嫌疑,而且如果不小心传错位不好判断。
这样的话小K就只能出杀手锏了:sh xxx.sh source=a.txt target=bak.txt
<code>for i in $* do export $i done logger 'info' "将原数据文件[${source}]复制到[${target}]" cp ${source} ${target}/<code>
Tips:
- 可以通过循环的方式和export直接将外部参数赋值给变量
0x04 变量未定义
哼哼哈hi,搞定。等等,万一小Q又来个异常测试,不给我传变量名可咋整?
可以在代码里加上set –o nounset。
<code>for i in $* do export $i done set -o nounset logger 'info' "将原数据文件[${source}]复制到[${target}]" cp ${source} ${target}/<code>
Tips:
- 当使用未定义的变量时,设置set -o nounset 可以让程序强制退出。老板再也不用担心rm -rf /${xxx}了
这些小技巧你学会了吗?
I will be back!
作者:范令凯
公众号:互联网技术到家
头条号:互联网技术到家