|

楼主 |
发表于 2005-5-16 13:06:01
|
显示全部楼层
Post by kiron
上面的die函数的使用:
f 中避免了用子shell来确保exit能从shell脚本中退出
那....
我要是在f中避免了用子shell,那也能确保exit能使脚本退出.
另外,若是为了使用die函数而使你的bash脚本少用了子shell,那岂不是把shell的功能减了一些?我认为得不偿失
因为不能用它来开发里面用了子shell的函数
或许我的理解有误,还请herberteuler兄继续指正
我是这样想的:比方说,下面这样的 C 程序 (只保留最简单的内容):
- #include <stdio.h>
- int main(int argc, char *argv[])
- {
- FILE *fp;
- int c;
- if ((fp = fopen(argv[1], "r")) == NULL)
- error(1, "cannot open %s", argv[1]); /* error 函数:见主题贴 */
- while ((c = fgetc(fp)) != EOF)
- putchar(c);
- fclose(fp);
- return 0;
- }
复制代码
它的功能很简单,就是打开一个文件 (由命令行提供),并且把它的内容输出到屏幕上。如果打开文件的操作不成功,在 C 里可以调用 exit 来强迫程序结束执行。下面是这个程序的 Shell 版本:
- #!/bin/sh
- test -e $1 || { echo "cannot open $1" 1>&2; exit 1; }
- cat $1
复制代码
这看上去很累,因为只用 cat 就可以完成功能了。然而我这里举的例子并不恰当。如果用 Shell 来写一个大程序,可能会遇到许多无法用一个命令就能实现的功能。比如我现在要完成的功能:
- # void getpkgdir(string pkg)
- getpkgdir()
- {
- local tmpfile="/tmp/dipmt.getpkgdir.$$"
- append DIPMT_TMPFILE $tmpfile
- trap "rm -f $DIPMT_TMPFILE; exit $DIPMT_GENERAL" 0 SIGINT SIGQUIT SIGKILL SIGTERM
- local d=$(pwd)
- cd $PKGASSISTDIR || die $DIPMT_GENERAL "package assistant directory $PKGASSISTDIR does not exist"
- local s=$(echo $1 | sed 's/\//\\\//g
- s/\./\\\./g')
- local n=$(find -mindepth 2 -maxdepth 2 -type d | grep "/$s$" | tee $tmpfile | wc -l)
- if test $n -eq 0 ; then
- die $DIPMT_PKGNFOUND "package $1 is not found"
- elif test $n -gt 1 ; then
- die $DIPMT_MULTIPKG "multiple packages found:
- $(cat $tmpfile | sed 's/^\.\// /')
- you must specify one of them"
- fi
- cat $tmpfile
- rm -f $tmpfile
- deappend DIPMT_TMPFILE $tmpfile
- cd $d
- }
复制代码
这个函数实际上是在完成 Gentoo 里 emerge package-name 的一步,查找名为 package-name 的软件包的 ebuild 的目录的功能。它有一个参数,就是软件包的名称。如果找到了,它将会把目录的绝对位置打印到标准输出;如果没有找到,则打印相应的错误信息并退出。这样,我就可以用一个赋值语句来获得一个软件包的目录:
- # in some function
- local pkgdir=$(getpkgdir $pkgname)
复制代码
我最初的设想是,如果 getpkgdir 没有找到与 $pkgname 匹配的软件包,就可以退出了;可是事实却不是这样。最终的解决方法,就像是上面那样。
当然,还有另一种方法可以解决问题,就是把临时文件作为参数来传递,这样便不必向标准输出上写内容了;不过仔细思考后我发现这两种方法都要解决同一个问题,就是要保存一个临时文件的列表来防止生成垃圾。最终我选择了第一种方法。
我想,如果用 Shell 来写大程序的话,像上面这样的功能是不可避免的。但是 Shell 语言的特殊性使得它没有提供像 C 里的 exit 函数这样的强有力的工具。由于子 Shell,Shell 里的 exit 并不能提供与 C 中的 exit 函数完全相同的功能。我不想因为要使用子 Shell 而无法实现在 C (或者 Perl 与 Python) 里很容易就可以实现的功能。 |
|