Wie ich fühle, ist es ein Fehler. Unten ist eine Art "Detektivgeschichte".
Ja, im exec.def
Code sehen wir:
if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
exit_shell (exit_value);
so, exec
würde bewirken , dass die Hülle a) für nicht-interaktiv Shell verlass mit false
„no_exit_on_failed_exec“ b) , wenn exec
wird in Subshell läuft
Wenn der Befehl für die interaktive Shell vorhanden ist, wird die Shell durch den aufgerufenen Befehl ersetzt:
exec
Diese eingebaute Shell ersetzt den aktuellen Prozess durch einen angegebenen Befehl. Wenn die Shell auf einen Befehl stößt, wird normalerweise ein untergeordneter Prozess angehalten, um den Befehl tatsächlich auszuführen.
Bei Verwendung des integrierten Befehls exec wird die Shell nicht gespalten, und der ausgeführte Befehl ersetzt die Shell . Wenn es in einem Skript verwendet wird, erzwingt es daher ein Beenden des Skripts, wenn der ausgeführte Befehl beendet wird .
Beispiel 15-24. Auswirkungen von 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.**
http://www.tldp.org/LDP/abs/html/internal.html#EXECREF
source
Befehl ruft keine Subshell auf - erzwingt die Ausführung aller Befehle in Ihrer aktuellen, aktiven Shell (wird z. B. zum Setzen von Variablen verwendet - nicht für eine Subshell, die beendet wird, sondern für Ihre aktuelle Shell). Nach dem Ausführen des Befehls sowohl mit source
als auch direkt in der Shell wird Ihre Shell beendet (dies ist das erwartete Verhalten).
Wenn ein Skript unter Verwendung von "source" ausgeführt wird, wird es in der vorhandenen Shell ausgeführt. Alle vom Skript erstellten oder geänderten Variablen bleiben verfügbar, nachdem das Skript abgeschlossen wurde.
http://ss64.com/bash/source.html
Ich habe es kompiliert bash-4.2
und im gdb
Debugger ausgeführt.
Dies sind die letzten Befehle, die vor dem Beenden ausgeführt werden:
(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]
Variablen drucken:
(gdb) p subshell_environment
$1 = 0
(gdb) p interactive
$2 = 0
(gdb) p no_exit_on_failed_exec
$3 = 0
Es stellt sich heraus, dass die Shell nicht interaktiv ist ( interactive=0
), während das eingebaute System beschafft wird exec
. Dies ist der Grund für ein solches Verhalten. Es widerspricht dem dokumentierten Verhalten, man könnte also sagen, Sie haben einen Fehler gefunden.
Die Änderung non-interactive
, interactive=0
geschieht hier ( 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;
wegen flags=14
.
flags
sind in der function source_file
( evalfile.c
) einen Level höher gesetzt :
#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);
Und die Definitionen sind:
#define FEVAL_BUILTIN 0x002
#define FEVAL_UNWINDPROT 0x004
#define FEVAL_NONINT 0x008
-> Flags 1110 = 14.
So, wie ich es verstehe, ist es ein Fehler: source
führt Befehle in der aktuellen Shell aus, setzt aber das Flag FEVAL_NONINT 0x008
- nicht interaktiv (Fehler hier):,
evalfile.c
in source_file
:
338 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
Ich habe ein Problem in einem Bug-Tracker erstellt:
http://savannah.gnu.org/support/index.php?108980
Würde es sehen.
EDIT1:
Als bash Supporter kommentierte das Ticket
"Die Shell ist derzeit nicht interaktiv, wenn ein Dateiargument in die integrierte Quelle eingelesen wird (interactive == 0), obwohl die Shell selbst interaktiv ist (interactive_shell == 1)."
Auch, wie er sagte, dürfte sich dieses Verhalten in naher Zukunft nicht ändern.
Die Frage scheint jetzt geschlossen.
bash
?