Назад | Перейти на главную страницу

подоболочка не создается, если запускать команды без пути?

Я читаю книгу "Командная строка Linux и Библия сценариев оболочки"3-е издание. На странице 279 я цитирую:

"Подстановка команд создает то, что называется subshell для запуска прилагаемой команды. Подоболочка - это отдельная дочерняя оболочка, созданная из оболочки, в которой выполняется сценарий. По этой причине любые переменные, которые вы создаете в сценарии, недоступны для команды подоболочки.

Подоболочки также создаются, если вы запускаете команду из командной строки с помощью ./ path, но они не будут созданы, если вы просто запустите команду без пути ".

Последнее предложение меня смущает. Я тестировал простой скрипт, который экспортирует некоторые переменные; переменные не будут существовать после того, как скрипт существует, однако скрипт вызывается из ./ путь, или поместите скрипт в /usr/bin и запустить его без пути. Мне кажется, что нет никакой разницы, как он вызывается относительно подоболочки.

Что я пропустил?

«Подстановка команд создает так называемую подоболочку для выполнения вложенной команды. Подоболочка - это отдельная дочерняя оболочка, созданная из оболочки, которая запускает сценарий.

Речь идет о таких конструкциях, как:

echo "$(date) `uname -r`"

В этом примере я вызываю две подоболочки, используя две разные поддерживаемые нотации для подоболочек. Первая подоболочка запускает date команда, а вторая подоболочка запускает uname команда. В echo Команда выполняется исходной оболочкой после завершения работы обеих подоболочек.

По этой причине любые переменные, которые вы создаете в сценарии, недоступны для команды подоболочки.

Здесь автор получил задом наперед. Переменные, созданные до вызова подоболочки, доступны для подоболочки. Переменные, созданные внутри подоболочки, доступны только для подоболочки и исчезнут после завершения работы подоболочки.

Подоболочки также создаются, если вы запускаете команду из командной строки с использованием пути ./, но они не создаются, если вы просто запускаете команду без пути ».

Очень непонятно, что здесь пытается сказать автор. Если вы вызываете внешнюю команду, произойдет следующее, независимо от того, вызывается она с путем или без него:

  • Оболочка forks, чтобы создать новый процесс.
  • Вновь созданный дочерний процесс выполняет любое указанное вами перенаправление ввода-вывода.
  • Дочерний процесс выполняет внешнюю команду, после чего процессы перестают быть оболочкой и становятся тем, чем является внешняя программа. (Что, конечно, может быть сценарием оболочки).

Это новый процесс, поэтому любые переменные, установленные внешней командой, будут недоступны для родительского процесса, как если бы это была подоболочка.

Автор мог иметь в виду один из следующих трех сценариев:

  • Внешняя команда представляет собой неправильно отформатированный сценарий, и в этом случае вызывающая оболочка может работать над неправильным форматированием, угадывая, какую оболочку использовать для интерпретации сценария. (Этот сценарий настолько непредсказуем, что я настоятельно рекомендую не полагаться на него. Правильный способ найти интерпретатор - иметь #! строка в начале скрипта.)
  • Возможно, вы вызываете внутреннюю команду, например read, который синтаксически выглядит как внешняя команда, найденная путем поиска PATH. Но даже если синтаксически он выглядит одинаково, он будет вести себя по-другому. поскольку read установит переменную, предназначенную для использования следующими командами, read сам должен произойти в текущем процессе без каких-либо fork вызов. (Даже внутренние команды, которые можно безопасно вызывать как подпроцесс, лучше выполнять в текущем процессе по соображениям производительности. Вызов fork вроде дорого.)
  • Вы могли получать команды оболочки, используя . file или source file. В таком случае file это не сценарий, но он чем-то похож. Все команды в file будет вызываться текущей оболочкой без предварительного вызова fork. (Но, конечно, команды внутри file может вызвать fork звонки). В этом случае любой #! линия в file будут игнорироваться, и любые переменные, установленные file будет доступен для вашей текущей оболочки.