本文这里说的shell指的是shell脚本语言,我们在使用shell脚本时,有时会感到困惑,即shell脚本里面的命令明明执行失败了,但是还可以继续执行,而不是自动退出,而这有时候确实也会导致我们非预期的行为。当我们习惯了其他的编程语言,突然遇到shell脚本的时候,确实难免会产生这样的疑惑。因为一般其他的编程语言出现报错的时候,只要没有捕捉异常,就会运行不成功而自动退出。至于为什么shell脚本语言和其他一般的编程语言会有这样的区别,还是得先大概了解一下shell脚本的运行机制。
shell脚本语言中,其由自己的语法和一些linux构成,在运行shell脚本的时候,实际上是在shell程序中逐条的执行这些语句。这里的shell程序和shell脚本语言不一样,shell程序就是一个可以和系统交互的程序,一般我们登录linux系统之后实际上就进入了shell。所以执行shell脚本实际上就是在shell中执行linux命令,当然shell语言有自己独特的语法,我们在这些语法的基础上加以一些linux命令就构成了shell脚本。要注意的是,linux命令和shell语言本身没有什么关系,因为比如我们常见的cd ls tar等这些命令,都是由一些独立的程序实现的,当然这些程序或预安装在系统里,或者是用户自己安装的。我们需要知道的是,shell脚本的运行实际上就是在shell程序中运行里面的语句,因此只要是可以成功运行的linux命令,都可以写入shell脚本中执行。
现在我们知道,shell脚本主要由shell语言自己的语法和一些独立的linux命令构成。因此,当linux命令运行不成功时,shell脚本自身并不会马上退出,而是会继续运行,因为这些命令本身是独立于shell脚本语言的。除非是shell语言自身的语法出错,那么shell脚本将会报错立马退出。
尽管linux命令和shell语言本身是独立的,但是shell脚本中每条命令的执行都会返回一个值,0表示成功,1表示未成功,可以用$?来捕捉一条命令的执行结果,然后再在脚本中加以判断以及实现相应的逻辑,而不是让其一直执行下去。
当然,如果我们对某部分命令需要很谨慎,只要其中一条命令异常没有执行成功,就让其退出,那么可以在这部分命令的开头加入set -e,这样set -e后面的命令只要有异常,脚本就会立马退出,而不是继续执行;如果想在某处开始结束这种设定,只需要在该处再写入set +e即可,这样这种有异常就立马退出的功能就会被关闭。
如下所示,从set -e开始,下面的cd tmp_dir和rm -rf *语句,只要有一条没有运行成功,脚本都会立马退出;然后从set +e开始,后面的语句又会恢复默认设定,即有异常还是会继续执行。这里如果没有set -e,那么假如/root下没有tmp_dir的话,/root下的所有内容都会被删除,这是非常危险的操作,但是加入了set -e,加入没有tmp_dir,那么cd tmp_dir这条命令没有执行成功的话,脚本就会立马退出,从而也就不会把root下的所有内容删除。
#!/bin/bash
cd /root
set -e
cd tmp_dir
rm -rf *
set +e
#
#any cmds here
#