config.status
我引用了生成的下一个代码片段configure
。
if test ! -f "$as_myself"; then
{ { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
{ (exit 1); exit 1; }; }
fi
代码片段中,{ (exit 1); exit 1; };
做了什么?只exit
在子 shell 中执行的目的是什么?
答案1
执行(exit 1);
是触发陷阱的最简单方法ERR
。如果set -e
有效,它也会触发立即退出。 (触发错误条件需要命令失败;exit
子 shell 中的失败值会导致子 shell 失败。)
exit 1;
不会做这两件事。
So{(exit 1); exit 1;}
可用于首先生成ERR
陷阱,这可能会执行一些对调试有用的操作,然后终止脚本并显示错误指示。
autoconf
但文件中的情况并非如此。autoconf
脚本依靠EXIT
陷阱来清理运行期间创建的临时文件。大多数 shell(包括)将在调用陷阱之前bash
根据命令中提供的值设置状态。这可以允许陷阱检测它是从错误还是正常终止中调用,并且还允许它确保在陷阱操作结束时正确设置退出状态。exit
EXIT
EXIT
然而,显然有些外壳不合作。这是来自autoconf
手动的:
某些 shell 脚本(例如由 生成的脚本
autoconf
)在退出前使用陷阱进行清理。如果最后一个 shell 命令以非零状态退出,则陷阱也会以非零状态退出,以便调用者可以知道发生了错误。不幸的是,在某些 shell(例如 Solaris)中
/bin/sh
,退出陷阱会忽略 exit 命令的参数。在这些 shell 中,陷阱无法确定它是由普通退出调用还是由退出 1 调用。不要直接调用 exit,而是使用AC_MSG_ERROR
可解决此问题的宏。
解决方法是确保$?
具有退出状态前该exit
命令被执行,因此当EXIT
陷阱执行时它肯定会具有该值。事实上,正是这个AC_MSG_ERROR
宏插入了奇怪的代码,并带有多余的大括号。
答案2
据我所知,这样做没有任何目的,没有什么可以通过启动子shell然后立即退出来直接实现。
像这样的事情很可能是自动生成代码的副作用 - 在某些情况下,可能会在子 shell 中执行其他命令,而这些命令是有意义的exit 1
。最终,通过允许生成代码插入一些在某些情况下没有任何功能的语句,生成代码很有可能在某种程度上得到简化,而每次生成“干净的代码”会更加复杂。要么是那个,要么是生成上述代码的代码写得不好:)
自由使用{...}
是另一个例子,它们中的大多数都是多余的,但是编写在每种情况下插入它们的代码更容易(也许在某些情况下您想要重定向块的输出/输入)而不是区分那些不需要的地方并省略它们。
答案3
(exit 1)
是一种简单的、可能是最简单的获取特定退出代码的方法(当然,在 1 的特殊情况下,还有更简单的方法)。但这不是本例的原因,因为没有检查退出代码。
放入子 shell 的目的exit
可能是不退出脚本(尽管使用 exit 来生成特定的退出代码)。