什么`{{(出口1); 出口1;}; }`是什么意思?

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宏插入了那些奇怪的代码,并带有多余的花括号。

  • @Ruslan:两个问题。(1) 最重要的是:`false` 不允许您设置状态代码,并且不能保证它返回什么非零状态。(2) `false` 通常不是内建的,所以它需要一个子进程;相比之下,大多数 shell 可以避免产生一个孩子来处理 `(exit 1)`。 (3认同)

Gra*_*eme 8

据我所知,这样做没有任何目的,通过启动子shell然后立即退出无法直接实现。

像这样的事情很可能是自动生成代码的副作用 - 在某些情况下,子shell中可能会执行其他exit 1有意义的命令。最终,通过允许它插入一些在某些情况下没有任何功能的语句,并且每次生成“干净代码”更复杂,生成代码很有可能在某种程度上得到简化。无论是那个还是上面生成的代码都写得不好:)

的自由使用{...}是另一个例子,它们中的大多数都是多余的,但是编写在每种情况下都插入它们的代码(可能在某些情况下您想重定向块的输出/输入)而不是区分那些不需要它们的地方并省略它们。