工作中时常在中见到set的这两个用法,但如同生活中的好多事情,习惯造成忽略,直至出现问题才导致关注。

1.set-e

set的-e参数,linux自带的说明如下:

"Exitimmediatelyifasimplecommandexitswithanon-zerostatus."

也就是说,在"set-e"以后出现的代码,一旦出现了返回值非零,整个都会立刻退出。有的人喜欢使用这个参数,是出于保证代码安全性的考虑。但有的时侯,这些美好的本意,也会造成严重的问题。

真实案例:

linuxset命令例子_linux中set命令_linux set命令

脚本a.sh开头使用了"set-e",且能正常运行。在几个月或更久之后,因需求升级,在脚本中降低了3行hadoop操作:

#!/bin/bash
set -e
...
/home/work/.../hadoop dfs -rmr /app/.../dir

linux set命令_linux中set命令_linuxset命令例子

/home/work/.../hadoop dfs -mkdir /app/.../dir /home/work/.../hadoop dfs -put file_1 /app/.../dir/ ...

这几行hadoop逻辑很简单:在hdfs上去除并新建一个目录,并将一份本地文件推送至这个目录,供后续使用。将这几行单拎下来,在行下执行,不仅提示待删掉的目录不存在,并没有哪些问题,文件还是会被推送到指定的地方。

但第一次执行这个脚本的时侯,却失败退出了,且造成调用该脚本的程序整体退出,导致了严重的后果。缘由是hdfs上还没有这个目录,rmr这一行会返回255,这个值被脚本前方的"set-e"捕捉到,直接造成了脚本退出。

linuxset命令例子_linux中set命令_linux set命令

新增的代码本身并没有问题,先删掉再新建目录,反倒是保证数据安全的比较规范的操作linux操作系统好吗,删掉命令本身的容错性,可以保证后续命令正常执行。事实是这个脚本有好几百行,且逻辑比较复杂,在降低这几行代码的时侯,开发人员早已不记得这个脚本里还有个"set-e"埋伏着了。

可见设置"set-e",在脚本开发过程中可能很有帮助,而在开发完成后linux定时器,非常是对于后期可能有升级的脚本,则可能是埋下了安全隐患。

2.set-opipefail

对于set命令-o参数的pipefail选项,linux是这样解释的:

"Ifset,thereturnvalueofapipelineisthevalueofthelast(rightmost)commandtoexitwithanon-zerostatus,orzeroifallcommandsinthepipelineexitsuccessfully.Thisoptionisdisabledbydefault."

设置了这个选项之后,包含管线命令的句子的返回值linux set命令linux set命令,会弄成最后一个返回非零的管线命令的返回值。听上去比较绕,虽然也很简单

# test.sh
set -o pipefail
ls ./a.txt |echo "hi" >/dev/null
echo $?

运行test.sh,由于当前目录并不存在a.txt文件,输出:

linuxset命令例子_linux set命令_linux中set命令

ls:./a.txt:Nosuchfileordirectory

1#设置了set-opipefail,返回从右往左第一个非零返回值,即ls的返回值1

注释掉set-opipefail这一行,再度运行,输出:

ls:./a.txt:Nosuchfileordirectory

0#没有set-opipefail,默认返回最后一个管线命令的返回值

本文原创地址://sclmfb.cn/srljsjbzsdyf.html编辑:刘遄,审核员:暂无