在shell中,source与.是等同的,而./是有些细微的不同的,尽管都是在执行命令或者脚本。
source或.执行后面的脚本,直到有return出现退出。
下面是在网上搜集的关于此的讨论(暂时没有看懂)
BASH脚本可以以 . 或 source内置命令来执行, 也可以直接执行脚本文件(需要首行有#!/path/to/bash并且文件是可执行的), 这两种情况是有一些微妙区别的.
1.
以.或source这两个等价的builtin来执行脚本时是在当前的SHELL解释器中直接读取命令来执行,
所以可以通过这个脚本改变当前SHELL的环境变量, 脚本中的exit所退出的也自然是当前这个SHELL,
这一点很可能不是大多数情况下的预期行为. 而直接执行脚本则会在一个子SHELL进程中读取脚本中的命令执行,
此时只能改变当前这个进程的环境变量, 不能上溯影响其父进程的环境块, 而exit也只是退出这个子进程而已.
在程序刚开始的地方往往会检查参数的合法性, 如果参数个数, 顺序或其它方面的要求不正确, 程序往往就没办法执行,
此时最经常的用法就是显示程序的usage信息, 然后用exit 1;来提前终止程序.
但这对于用.或source执行脚本的情况来说就会错误地退出当前的shell, 怎么样在任何情况下都能让程序全身而退: SHLVL 变量,
它是shell level的简写. 意思是SHELL被嵌套的次数.
[ ! -f ] && { echo "FILE doesn't exist"; [ $SHLVL -gt 1 ] && exit 1; [ $SHLVL -eq "1" ] && return; }
上
面这个命令检查了 是否是一个普通文件, 如果不是就显示一条错误信息说该文件不存在, 然后检查 $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.
下面是man中的关于source
source filename [arguments]
Read
and execute commands from filename in the current shell environment and
return the exit status of the last command executed from filename. If
filename does not contain a slash, file names in PATH are used to find
the directory containing filename. The file searched for in PATH need
not be executable. When bash is not in posix mode, the current
directory is searched if no file is found in PATH. If the sourcepath
option to the shopt builtin command is turned off, the PATH is not
searched. If any arguments are supplied, they become the positional
parameters when filename is executed. Otherwise the positional
parameters are unchanged. The return status is the status of the last
command exited within the script (0 if no commands are executed), and
false if filename is not found or cannot be read.
阅读(2542) | 评论(0) | 转发(0) |