MS.*_*Kim 28 shell shell-script configure
我引用了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
Run Code Online (Sandbox Code Playgroud)
在代码片段中,有什么作用{ (exit 1); exit 1; };?只exit在子shell中做什么的目的是什么?
ric*_*ici 34
执行(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,退出陷阱会忽略退出命令的参数。在这些 shell 中,陷阱无法确定它是由普通出口调用还是由出口 1 调用。不要直接调用 exit,而是使用AC_MSG_ERROR具有解决此问题的方法的宏。
解决方法是确保$?有退出状态之前的exit执行命令,这样当它必定会对这个值EXIT执行陷阱。事实上,正是AC_MSG_ERROR宏插入了那些奇怪的代码,并带有多余的花括号。
据我所知,这样做没有任何目的,通过启动子shell然后立即退出无法直接实现。
像这样的事情很可能是自动生成代码的副作用 - 在某些情况下,子shell中可能会执行其他exit 1有意义的命令。最终,通过允许它插入一些在某些情况下没有任何功能的语句,并且每次生成“干净代码”更复杂,生成代码很有可能在某种程度上得到简化。无论是那个还是上面生成的代码都写得不好:)
的自由使用{...}是另一个例子,它们中的大多数都是多余的,但是编写在每种情况下都插入它们的代码(可能在某些情况下您想重定向块的输出/输入)而不是区分那些不需要它们的地方并省略它们。