安全撤退的一句话bash 脚本
时间:2005-09-05 来源:slimzhao
1. 以.或source这两个等价的builtin来执行脚本时是在当前的SHELL解释器中直接读取命令来执行, 所以可以通过这个脚本改变当前SHELL的环境变量, 脚本中的exit所退出的也自然是当前这个SHELL, 这一点很可能不是大多数情况下的预期行为. 而直接执行脚本则会在一个子SHELL进程中读取脚本中的命令执行, 此时只能改变当前这个进程的环境变量, 不能上溯影响其父进程的环境块, 而exit也只是退出这个子进程而已. 在程序刚开始的地方往往会检查参数的合法性, 如果参数个数, 顺序或其它方面的要求不正确, 程序往往就没办法执行, 此时最经常的用法就是显示程序的usage信息, 然后用exit 1;来提前终止程序. 但这对于用.或source执行脚本的情况来说就会错误地退出当前的shell, 怎么样在任何情况下都能让程序全身而退: SHLVL 变量, 它是shell level的简写. 意思是SHELL被嵌套的次数.
[ ! -f $1 ] && { echo "FILE $1 doesn't exist"; [ $SHLVL -gt 1 ] && exit 1; [ $SHLVL -eq "1" ] && return; }
上面这个命令检查了$1 是否是一个普通文件, 如果不是就显示一条错误信息说该文件不存在, 然后检查 $SHLVL是否大于1, 如果是的话就可以安全地用exit退出, 此时后面那句话也就不必执行了, 如果不是的那它的值其实也只能是1了(这个变量是SHELL中的只读变量, 不能以可编程的方法来改变), 这时说明是在当前的shell执行的, 用return;语句退出.
那么是不是两种情况都可以简单地用return; 来退出呢. 不是!
简单地执行下面的脚本(tmp.sh)
#!/bin/bash
{
return;
}
echo "After return";
如果是以. tmp.sh来执行就没问题, 如果以./tmp.sh来执行则会显示一条错误信息:
./tmp.sh: line 5: return: can only `return' from a function or sourced script
说的很明白, return只能用在直接解释执行的脚本或函数中. 上面的{ ... }只是一个命令组, 不是函数(不要认为是个匿名函数)
在很多的程序语言里, return也的确只能用于函数的返回, 在SHELL编程中它也可以出现在程序最外面层的位置. 只不过这种用法只对所谓sourced 脚本才有特殊语意.
标准的SHELL内置帮助是没有提及这个特殊用法的, 反而前面的错误信息提到了这一点:
bash-2.05b$ help return
return: return [n]
Causes a function to exit with the return value specified by N. If N
is omitted, the return status is that of the last command.