的文档exec
说,如果当前外壳是非交互式的并且execfail
未设置选项,则在出现错误的情况下它将退出外壳。
我注意到交互式bash shell中有一个奇怪的行为,但是我无法用文档来解释。这个命令
exec non-existent-file
产生错误消息,并且外壳程序保持活动状态,如预期的那样。但是,如果我将相同的命令放入文件和source
该文件中,则当前的shell将由失败的exec退出。
有人可以帮我理解为什么会这样吗?
据我所知,这是一个错误。以下是某种“侦探小说”。
是的,在exec.def
代码中,我们看到:
if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
exit_shell (exit_value);
因此,exec
将导致退出外壳a)在非交互式外壳上使用false
“ no_exit_on_failed_exec” b)exec
在子外壳中运行时
对于交互式外壳程序,如果存在该命令,则该外壳程序将由调用的命令替换:
执行
这个内置的shell用指定的命令替换当前进程。通常,当外壳程序遇到命令时,它将派生一个子进程来实际执行该命令。使用内置的exec,shell不会派生,并且exec'命令替换了shell。因此,当在脚本中使用时,当exec'ed命令终止时,它会强制退出脚本。
示例15-24 执行的影响
#!/bin/bash exec echo "Exiting \"$0\" at line $LINENO." # Exit from script here. # $LINENO is an internal Bash variable set to the line number it's on. **# The following lines never execute.**
source
command不调用subshell-强制所有命令在您当前的活动shell中执行(例如,用于设置变量-不是要退出的某些subshell,而是您当前的shell)。因此source
,在shell中直接执行命令之后,shell将终止(这是预期的行为)。
当使用`source'运行脚本时,它将在现有的shell中运行,脚本完成后,由脚本创建或修改的任何变量将保持可用。http://ss64.com/bash/source.html
我已经编译bash-4.2
并在gdb
调试器中运行了它。
这些是退出前要执行的最后命令:
(gdb)
bash: exec: non-existing-file: не найден
163 exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */
(gdb)
165 goto failed_exec;
(gdb)
235 FREE (command);
(gdb)
237 if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
(gdb)
238 exit_shell (exit_value);
(gdb)
[Inferior 1 (process 4034) exited with code 0177]
打印变量:
(gdb) p subshell_environment
$1 = 0
(gdb) p interactive
$2 = 0
(gdb) p no_exit_on_failed_exec
$3 = 0
事实证明,interactive=0
在采购内置组件时,外壳是非交互式()的exec
。这就是这种行为的原因。它与记录的行为相矛盾,因此,也许有人会说,您发现了一个错误。
对non-interactive
,的更改interactive=0
发生在此处(evalfile.c
):
interactive:
Old value = 1
New value = 0
_evalfile (filename=0xa014c8 "exec1.sh", flags=14)
at evalfile.c:226
223 if (flags & FEVAL_NONINT)
224 interactive = 0;
因为flags=14
。flags
在功能source_file
(evalfile.c
)中设置为更高的级别:
#1 0x0000000000485dcf in source_file (filename=0x9fb8c8 "exec1.sh", sflags=0)
338 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
339 if (sflags)
340 flags |= FEVAL_NOPUSHARGS;
341 /* POSIX shells exit if non-interactive and file error. */
342 if (posixly_correct && interactive_shell == 0 && executing_command_builtin == 0)
343 flags |= FEVAL_LONGJMP;
344 rval = _evalfile (filename, flags);
定义是:
#define FEVAL_BUILTIN 0x002
#define FEVAL_UNWINDPROT 0x004
#define FEVAL_NONINT 0x008
->标志1110 = 14。
所以,按照我的理解,这是一个错误:source
在当前shell执行命令,但套旗FEVAL_NONINT 0x008
-非交互式(错误这里):evalfile.c
在source_file
:
338 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
我在错误跟踪器上创建了一个问题:
http://savannah.gnu.org/support/index.php?108980
会看的。
编辑1:作为bash支持者在票证上评论
“尽管外壳本身是交互式的(interactive_shell == 1),但是当读取源内置文件的文件参数时,外壳当前不是交互式的(交互式== 0)。”
而且,正如他所说,这种行为在不久的将来很可能不会改变。
这个问题似乎已经结束。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句