工作中经常在shell脚本中看到set的这两个用法,但就像生活中的很多事情,习惯导致忽视,直到出现问题才引起关注。

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,默认返回最后一个管道命令的返回值

shell 中的 set命令 -e -o 选项作用相关推荐

  1. linux shell 中的sleep命令

    开始还以为是这样的语法: sleep(1), 后面发现是: linux shell 中的sleep命令 分类: LINUX 在有的shell(比如linux中的bash)中sleep还支持睡眠(分,小 ...

  2. linux脚本添加source,shell中的source命令的巧妙用法

    首先,通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录.例如,当我们修改了/etc/profile文件,并想让它立刻生效,而不用重新登录,就可以使用source命令,如sourc ...

  3. [linux运维]1@linux shell中的实用命令

    函数传参 shell中如何写一个函数呢? 这个问题, 首先说, shell中的函数, 在方法体里, 没有形参, 都是通过默认的特殊值获得的, 比如$1, $2, 参数的数量用. 而传参呢, 也是通过方 ...

  4. shell中的declare命令

    declare命令有如下选项: -a 声明一个数组 -i 声明一个整型 -f 打印所有函数定义 -F 仅打印函数名字 -r 声明一个readonly变量,该变量的值无法改变,并且不能为unset -x ...

  5. shell 中的 set命令简介

    shell 中的调试 set命令简介 set命令简介 语法 常用命令说明 其他执行shell脚本调试的方法 set命令简介 使用内置命令set可以调试Shell脚本的指定部分. set命令通过选项开关 ...

  6. shell中的expect命令

    原文https://blog.csdn.net/jxdl6655/article/details/78626749 expect可以实现shell实现不了的用户交互的需求.expect可以将交互写在一 ...

  7. shell中 的 export命令

    export 功能说明:设置或显示环境变量. 语 法:export [-fnp][变量名称]=[变量设置值] 补充说明:在shell中执行程序时,shell会提供一组环境变量.export可新增,修改 ...

  8. shell中一些特殊命令|: 管道命令。;;在前一个命令结束时,而忽略其返回值,继续执行下一個命令。

    shell传递参数 $0 对应的是当前 Shell 脚本程序的名称,$#对应的是总共有几个参数,$*对应的是所有位置的参数值,$?对应的是显示上一次命令的执行返回值,而$1.$2.$3--则分别对应着 ...

  9. Shell中的Sed命令详解

    简介 sed 是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为"模式空间"(pattern space),接着用sed命令处理缓冲区中的内容,处 ...

最新文章

  1. 博士后工作站来了!智源研究院获得正式授牌
  2. 学生信息管理C语言 密码,求学生信息管理系统C语言版
  3. USTC 2011 homework list [现代软件工程 作业]
  4. 获取windows所有端口
  5. SpringBoot高级篇JdbcTemplate之数据查询上篇
  6. python和c先学哪个-对于初学者而言,python和 c语言先学哪个好
  7. python中大于0的元素全部转化为1,小于0的元素全部转化为0的代码
  8. SQL Server事务、视图和索引
  9. Android App安全防范措施的小结
  10. 2018 6月底阿里、网易面试经历简单回忆
  11. Redis 到底是怎么实现“附近的人”这个功能的呢?
  12. 曲率、曲率圆和曲率半径
  13. 获取微信公众号二维码接口
  14. 创建一个背景色为蓝色的Pygame窗口
  15. 追光而遇,沐光而行:相约未来GIS实验室
  16. mysql表名备注_「备注」mysql添加备注信息 - seo实验室
  17. 一起安装多个depot文件
  18. Oracle备份恢复(一)
  19. [H5案例课程]连连看H5小游戏的制作-岑远科-专题视频课程
  20. Python工资一般多少?

热门文章

  1. 内存管理范围和@property
  2. 学霸网站-Beta版本发布说明
  3. 采用8种相位,每种相位各有两种幅度的QAM调制方法,在1200Baud的信号传输速率下能达到的网数据传输速率为( )
  4. 2017/Province_C_C++_B/2/等差素数列
  5. 63. Unique Paths II 不同路径 II
  6. 16. 3Sum Closest 最接近的三数之和
  7. 2014\Province_C_C++_B\1 啤酒和饮料
  8. 【机器视觉】 else算子
  9. 【Qt】Qt5.12连接MySQl5.7(亲自测试成功)
  10. 数据结构与算法之美01-开篇词