Como eu sinto, é um bug. Abaixo está algum tipo de "história de detetive".
Sim, no código exec.def
, vemos:
if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
exit_shell (exit_value);
então, exec
causaria a saída do shell
a) no shell não interativo com false
"no_exit_on_failed_exec"
b) quando exec
está sendo executado em subshell
Para o shell interativo, se o comando existir, o shell será substituído por o comando invocado:
O comandoexec
This shell builtin replaces the current process with a specified command. Normally, when the shell encounters a command, it forks off a child process to actually execute the command. Using the exec builtin, the shell does not fork, and the command exec'ed replaces the shell. When used in a script, therefore, it forces an exit from the script when the exec'ed command terminates.
Example 15-24. Effects of exec
#!/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
não chama subshell - força todos os comandos a executar no seu shell atual ativo (ele é usado, por exemplo, para definir variáveis - não para algum subshell que irá sair, mas para o seu shell atual). Então, depois de executar o comando com source
e diretamente no shell, seu shell terminará (é o comportamento esperado).
When a script is run using 'source' it runs within the existing shell, any variables created or modified by the script will remain available after the script completes. http://ss64.com/bash/source.html
Eu compilei bash-4.2
e o executei em gdb
debugger.
Estes são os últimos comandos que estão sendo executados antes da saída:
(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]
Imprimindo as variáveis:
(gdb) p subshell_environment
$1 = 0
(gdb) p interactive
$2 = 0
(gdb) p no_exit_on_failed_exec
$3 = 0
O shell não é interativo ( interactive=0
) durante a origem do exec
embutido. Essa é a razão para tal comportamento.
Isso contradiz o comportamento documentado, portanto, pode-se dizer que você encontrou um bug.
A alteração para non-interactive
, interactive=0
, acontece aqui ( 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;
por causa de flags=14
.
flags
estão definidos em um nível mais alto, na função 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);
E as definições são:
#define FEVAL_BUILTIN 0x002
#define FEVAL_UNWINDPROT 0x004
#define FEVAL_NONINT 0x008
- > sinalizadores 1110 = 14.
Então, pelo que entendi, é um erro: source
executa comandos no shell atual, mas define o sinalizador FEVAL_NONINT 0x008
- não interativo
(bug aqui):
evalfile.c
, em source_file
:
338 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
Eu criei um problema em um rastreador de bugs:
Assista.
EDIT1: Como o apoiador bash comentou no ticket
"The shell is not currently interactive when reading a file argument to the source builtin (interactive == 0), though the shell itself is interactive (interactive_shell == 1)."
Além disso, como ele disse, esse comportamento provavelmente não será alterado no futuro próximo.
A pergunta parece encerrada agora.