Кажется, я неправильно понимаю правило Bash для создания подоболочки. Я думал, что круглые скобки всегда создают подоболочку, которая запускается как собственный процесс.
Тем не менее, это не так. В фрагменте кода A (ниже) вторая sleep
команда не выполняется в отдельной оболочке (как определено pstree
в другом терминале). Тем не менее, в фрагменте кода В, вторая sleep
команда делает работать в отдельной оболочке. Единственная разница между фрагментами заключается в том, что второй фрагмент содержит две команды в скобках.
Может кто-нибудь объяснить, пожалуйста, правило, когда создаются подоболочки?
КОД СНИППЕТА А:
sleep 5
(
sleep 5
)
КОД СНИППЕТА B:
sleep 5
(
x=1
sleep 5
)
источник
fork
а дочерний процесс (для выполнения внешних команд) создается путем вызоваfork + exec
. Но ваш первый параграф говорит о том, чтоfork + exec
это также называется subshell. Что я здесь не так делаю?fork
+exec
не вызывается для подоболочки, она вызывается для внешней команды. Без какой-либо оптимизации естьfork
вызов для подоболочки и еще один для внешней команды. Я добавил подробное описание потока в мой ответ.(...)
(в базовом случае) может или не может быть вызова,exec
зависит от того, есть ли у подоболочки какая-либо внешняя команда для выполнения, в то время как в случае выполнения какой-либо внешней команды это должно бытьfork + exec
.date
в оболочке?strace -f -e clone,execve,write bash -c 'date'
иstrace -f -e clone,execve,write bash -c 'date; true'
Из Расширенного руководства по программированию Bash :
«Как правило, внешняя команда в сценарии разветвляется на подпроцесс, а встроенная Bash - нет. По этой причине встроенные команды выполняются быстрее и используют меньше системных ресурсов, чем их внешние эквиваленты команд».
И немного дальше вниз:
«Список команд, заключенный в скобки, работает как подоболочка».
Примеры:
Пример использования кода OPs (с более коротким сном, потому что я нетерпеливый):
Выход:
источник
sleep
будет выполняться в подоболочке (возможно, в процессе подоболочки, поскольку он является встроенным, а не подпроцессом подоболочки). Однако, в любом случае, я ожидал, что существует подоболочка, то есть подпроцесс Bash в родительском процессе Bash. Для фрагмента B выше, это не так.sleep
оно не является встроенным, я ожидаю, что второйsleep
вызов в обоих фрагментах будет выполняться в подпроцессе процесса subshell.$BASHPID
переменной. К сожалению, то, как ты это делал, не дало тебе всей истории, которой я верю. Смотрите мой добавленный вывод в ответе.Дополнительное примечание к ответу @Gilles.
Как сказал Жиль:
The parentheses always start a subshell.
Тем не менее, числа, которые имеют такие суб-оболочки могут повторяться:
Как вы можете видеть, $$ повторяется, как и ожидалось, потому что (выполните эту команду, чтобы найти правильную
man bash
строку):То есть: если оболочка не инициализирована повторно, $$ остается тем же.
Или с этим:
$$
Это идентификатор текущей оболочки (не подоболочки).источник