的文档exec说,如果当前 shell 是非交互式的并且execfail没有设置选项,它会在出错的情况下退出 shell 。
我注意到交互式 bash shell 中有一个奇怪的行为,但我无法用文档解释。这个命令
exec non-existent-file
Run Code Online (Sandbox Code Playgroud)
产生一条错误消息,并且 shell 保持活动状态,正如预期的那样。但是如果我将相同的命令放入一个文件和source那个文件中,当前的 shell 将被失败的 exec 退出。
有人可以帮助我理解为什么会发生这种情况吗?
据我感觉,这是一个错误。下面是某种“侦探故事”。
\n\n是的,在exec.def代码中我们看到:
if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))\n exit_shell (exit_value);\nRun Code Online (Sandbox Code Playgroud)\n\n因此,当在子 shell 中运行时exec,会导致在非交互式 shell 上使用false“no_exit_on_failed_exec”退出 shell\nb)exec
对于交互式 shell,如果该命令存在,则该 shell 将替换为\n调用的命令:
\n\n\n\n\n执行
\n\n此 shell 内置命令用指定的\n 命令替换当前进程。通常,当 shell 遇到命令时,它会派生出一个\n 子进程来实际执行该命令。\n 使用 exec 内置命令,\n shell 不会派生,并且命令 exec\'ed 会替换 shell。\因此,当在脚本中使用时,当执行的命令终止时,它会强制退出脚本。
\n\n示例 15-24。执行的效果
\n\nRun Code Online (Sandbox Code Playgroud)\n\n \n#!/bin/bash\nexec echo "Exiting \\"$0\\" at line $LINENO." # Exit from script here.\n# $LINENO is an internal Bash variable set to the line number it\'s on.\n**# The following lines never execute.**\n
sourcecommand 不会调用 subshell - 它强制所有命令在当前的活动 shell 中执行(例如,它用于设置变量 - 不是用于将退出的某些子 shell,而是用于当前的 shell)。source因此,在 shell 中直接执行命令后,您的 shell 将终止(这是预期的行为)。
\n\n\n当使用“source”运行脚本时,它会在现有 shell 中运行,\n 脚本创建或修改的任何变量将在脚本完成后保持可用。\n http://ss64.com/bash/source .html
\n
我已经编译bash-4.2并在gdb调试器中运行它。
这些是退出前执行的最后命令:
\n\n(gdb) \nbash: exec: non-existing-file: \xd0\xbd\xd0\xb5 \xd0\xbd\xd0\xb0\xd0\xb9\xd0\xb4\xd0\xb5\xd0\xbd\n163 exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */\n(gdb) \n165 goto failed_exec;\n(gdb) \n235 FREE (command);\n(gdb) \n237 if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))\n(gdb)\n238 exit_shell (exit_value);\n(gdb)\n[Inferior 1 (process 4034) exited with code 0177]\nRun Code Online (Sandbox Code Playgroud)\n\n打印变量:
\n\n(gdb) p subshell_environment \n$1 = 0\n(gdb) p interactive\n$2 = 0\n(gdb) p no_exit_on_failed_exec \n$3 = 0\nRun Code Online (Sandbox Code Playgroud)\n\n事实证明,interactive=0在获取内置exec. 这就是这种行为的原因。\n它与记录的行为相矛盾,因此,有人可能会说,您发现了一个错误。
non-interactive, ,的更改interactive=0发生在 ( evalfile.c) 处:
interactive:\nOld value = 1\nNew value = 0\n_evalfile (filename=0xa014c8 "exec1.sh", flags=14)\nat evalfile.c:226\n223 if (flags & FEVAL_NONINT)\n224 interactive = 0;\nRun Code Online (Sandbox Code Playgroud)\n\n由于flags=14.\nflags被设置为更高的级别,在函数source_file( evalfile.c) 中:
#1 0x0000000000485dcf in source_file (filename=0x9fb8c8 "exec1.sh", sflags=0)\n\n338 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;\n339 if (sflags)\n340 flags |= FEVAL_NOPUSHARGS;\n341 /* POSIX shells exit if non-interactive and file error. */\n342 if (posixly_correct && interactive_shell == 0 && executing_command_builtin == 0)\n343 flags |= FEVAL_LONGJMP;\n344 rval = _evalfile (filename, flags);\nRun Code Online (Sandbox Code Playgroud)\n\n定义是:
\n\n#define FEVAL_BUILTIN 0x002\n#define FEVAL_UNWINDPROT 0x004\n#define FEVAL_NONINT 0x008\nRun Code Online (Sandbox Code Playgroud)\n\n-> 标志 1110 =14。
\n\n因此,据我了解,这是一个错误:source在当前 shell 中执行命令,但设置标志FEVAL_NONINT 0x008- 非交互式\n(此处为错误):\n evalfile.c,位于source_file:
338 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;\nRun Code Online (Sandbox Code Playgroud)\n\n我在错误跟踪器上创建了一个问题:
\n\nhttp://savannah.gnu.org/support/index.php?108980
\n\n会看的。
\n\nEDIT1:\n作为 bash 支持者对票证的评论
\n\n\n\n\n“当读取文件参数到内置源时,shell 当前不是交互式的(interactive == 0),尽管 shell 本身是交互式的(interactive_shell == 1)。”
\n
而且,正如他所说,这种行为在不久的将来可能不会改变。
\n\n这个问题现在似乎已经结束了。
\n