Як я відчуваю, це помилка. Нижче наводиться якась "детективна історія".
Так, у exec.defкоді ми бачимо:
if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0))
exit_shell (exit_value);
таким чином, execможе викликати вихід оболонки а) на неінтерактивну оболонку з false"no_exit_on_failed_exec" b) під execчас запуску в нижній частині
Для інтерактивної оболонки, якщо команда існує, оболонка замінюється командою, що викликається:
виконувати
Ця вбудована оболонка замінює поточний процес заданою командою. Зазвичай, коли оболонка стикається з командою, вона змушує дочірній процес фактично виконувати команду.
Використовуючи вбудований exec, оболонка не розщеплюється, а команда exec'ed замінює оболонку . Тому при використанні в скрипті він примушує вихід із сценарію, коли команда 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.**
http://www.tldp.org/LDP/abs/html/internal.html#EXECREF
sourceкоманда не викликає subshell - вона змушує всі команди виконуватись у вашій поточній, активній оболонці (вона використовується, наприклад, для встановлення змінних - не для деякої підпакеті, яка вийде, а для вашої поточної оболонки). Тож після виконання команди як з sourceоболонкою, так і безпосередньо в оболонці, ваша оболонка припиниться (це очікувана поведінка).
Коли сценарій запускається з використанням "source", він запускається в межах наявної оболонки, будь-які змінні, створені або модифіковані сценарієм, залишаться доступними після завершення сценарію.
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виконує команди в поточній оболонці, але встановлює прапор FEVAL_NONINT 0x008- неінтерактивний (помилка тут):,
evalfile.cу source_file:
338 flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
Я створив проблему в трекері помилок:
http://savannah.gnu.org/support/index.php?108980
Подивився б це.
EDIT1: Як прокоментував білет прихильник басу
"Оболонка наразі не є інтерактивною, коли читає аргумент файлу до вбудованого джерела (interactive == 0), хоча сама оболонка є інтерактивною (interactive_shell == 1)."
Також, за його словами, ця поведінка, швидше за все, не зміниться найближчим часом.
Питання зараз здається закритим.
bash?