转载:http://q928856957.iteye.com/blog/2227850
linux
1. set -e
set命令的-e参数,linux自带的说明以下:
"Exit immediately if a simple command exits with a non-zero status."
也就是说,在"set -e"以后出现的代码,一旦出现了返回值非零,整个脚本就会当即退出。有的人喜欢使用这个参数,是出于保证代码安全性的考虑。但有的时候,这种美好的初衷,也会致使严重的问题。
真实案例:
脚本a.sh开头使用了"set -e",且能正常运行。在几个月或更久之后,因需求升级,在脚本中增长了3行hadoop操做:
#!/bin/bash
set -e
...
/home/work/.../hadoop dfs -rmr /app/.../dir
/home/work/.../hadoop dfs -mkdir /app/.../dir
/home/work/.../hadoop dfs -put file_1 /app/.../dir/
...
这几行hadoop命令逻辑很简单:在hdfs上清除并新建一个目录,并将一份本地文件推送至这个目录,供后续使用。将这几行单拎出来,在命令行下执行,除了提示待删除的目录不存在,并无什么问题,文件仍是会被推送到指定的地方。
但第一次执行这个脚本的时候,却失败退出了,且致使调用该脚本的程序总体退出,形成了严重的后果。缘由是hdfs上尚未这个目录,rmr这一行会返回255,这个值被脚本前方的"set -e"捕捉到,直接致使了脚本退出。
新增的代码自己并无问题,先删除再新建目录,反而是保证数据安全的比较规范的操做,删除命令自己的容错性,能够保证后续命令正常执行。事实是这个脚本有好几百行,且逻辑比较复杂,在增长这几行代码的时候,开发人员已经不记得这个脚本里还有个"set -e"埋伏着了。
可见设置"set -e",在脚本开发过程当中可能颇有帮助,而在开发完成后,特别是对于后期可能有升级的脚本,则多是埋下了安全隐患。
2. set -o pipefail
对于set命令-o参数的pipefail选项,linux是这样解释的:
"If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status,or zero if all commands in the pipeline exit successfully. This option is disabled by default."
设置了这个选项之后,包含管道命令的语句的返回值,会变成最后一个返回非零的管道命令的返回值。听起来比较绕,其实也很简单:
# test.sh
set -o pipefail
ls ./a.txt |echo "hi" >/dev/null
echo $?
运行test.sh,由于当前目录并不存在a.txt文件,输出:
ls: ./a.txt: No such file or directory
1 #设置了set -o pipefail,返回从右往左第一个非零返回值,即ls的返回值1
注释掉set -o pipefail这一行,再次运行,输出:
ls: ./a.txt: No such file or directory
0 # 没有set -o pipefail,默认返回最后一个管道命令的返回值
安全