Чи дійсно круглі дужки ставлять команду в підшарок?


94

З того, що я прочитав, введення команди в круглі дужки повинно запускати її в нижній частині, аналогічно виконанню сценарію. Якщо це правда, як вона бачить змінну x, якщо x не експортується?

x=1

Запуск (echo $x)в командному рядку призводить до 1

Запуск echo $xсценарію не призводить до нічого, як очікувалося

Відповіді:


134

Підскладок починається як майже ідентична копія оригінального процесу оболонки. Під кришкою оболонка викликає forkсистемний виклик 1 , який створює новий процес, код і пам'ять якого - копії 2 . Коли створено нижню частину корпусу, різниці між нею та її батьком є ​​дуже мало. Зокрема, вони мають однакові змінні. Навіть $$спеціальна змінна зберігає однакове значення в підрозділах: це вихідний ідентифікатор процесу оболонки. Аналогічно $PPIDє ідентифікатор PID вихідної оболонки.

Кілька оболонок змінюють декілька змінних в нижній частині корпусу. Bash встановлює BASHPIDPID процесу оболонки, який змінюється в підрозділах. Bash, zsh і mksh організують $RANDOMотримання різних значень у батьківській та в нижній частині. Але крім вбудованих спеціальних випадків на кшталт цього, всі змінні мають те саме значення в підшкільній оболонці, як і в початковій оболонці, той же статус експорту, той же статус лише для читання тощо. інші настройки також успадковуються.

Подоболочка творець (…)має ті ж дескриптори файлів , як його творець. Деякі інші засоби створення підшаровок змінюють деякі дескриптори файлів перед виконанням коду користувача; наприклад, ліва частина труби працює в нижній частині корпусу 3 зі стандартним виходом, з'єднаним з трубою. Підсерія також починається з того ж поточного каталогу, тієї ж маски сигналу тощо. Одним з небагатьох винятків є те, що підрозділи не успадковують власні пастки: ігноровані сигнали ( ) залишаються ігнорованими в підрозділі, але інші пастки ( SIGNAL ) скидаються. до дії за замовчуванням 4 .trap '' SIGNALtrap CODE

Таким чином, додаткова оболонка відрізняється від виконання сценарію. Сценарій - це окрема програма. Ця окрема програма може бути збігом випадкових випадків також і скриптом, який виконується тим же інтерпретатором, що і батьківський, але цей збіг не надає окремій програмі особливої ​​видимості щодо внутрішніх даних батьків. Неекспортні змінні є внутрішніми даними, тому коли інтерпретатор дочірнього сценарію оболонки виконується , він не бачить цих змінних. Експортовані змінні, тобто змінні середовища, передаються виконуваним програмам.

Таким чином:

x=1
(echo $x)

друкує, 1оскільки нижня оболонка - це реплікація оболонки, яка породила її.

x=1
sh -c 'echo $x'

трапляється запускати оболонку як дочірній процес оболонки, але xдругий рядок не має більшого зв'язку з xдругою лінією, ніж у

x=1
perl -le 'print $x'

або

x=1
python -c 'print x'

1 Виняток становить ksh93оболонка, де оптимізація розгортання та більша частина її побічних ефектів імітуються.
2 Семантично це копії. З точки зору впровадження, багато обміну відбувається.
3 Для правого боку це залежить від оболонки.
4 Якщо ви перевірите це, зауважте, що такі речі$(trap) можуть повідомляти про пастки оригінальної оболонки. Зауважте також, що у багатьох оболонках є помилки у кутових корпусах із пастками. Наприклад, ninjalj зазначає, що, починаючи з bash 4.3, bash -x -c 'trap "echo ERR at \$BASH_SUBSHELL \$BASHPID" ERR; set -E; false; echo one subshell; (false); echo two subshells; ( (false) )'запускає ERRпастку з вкладеної нижньої оболонки у випадку "дві підзахисні частини", але не ERRпастка з проміжної нижньої оболонки - set -Eваріант повинен розповсюджуватиERRпастка до всіх підпакетів, але проміжна піддошка оптимізована і тому не існує для запуску її ERRпастки.


2
@Kusalananda No. ( x=out; (x=in; echo $x))
Жиль

2
@ flow2k Це порядок розширення для речей, що відбуваються на одному рівні. Але також потрібно врахувати, як розширення поєднується з оцінкою. Коли розширення вимагає оцінки вкладеної конструкції, спочатку оцінюється внутрішня конструкція. Так, наприклад, щоб оцінити echo $(x=2; echo $x), фрагмент $(x=2; echo $x)потрібно розширити. Для цього потрібна оцінка команди x=2; echo $x. Розширення $xтрапляється під час цієї оцінки після оцінки частини x=2.
Жиль

2
@ flow2k Не існує порядку між розширенням параметрів і підстановкою команд. Зауважте, що це речення використовує крапки з комою для розділення кроків розширення, але розширення параметрів та підміна команд знаходяться в одному і тому ж розділі з крапкою з комою (так, це тонко). Порядок має значення, коли одна з частин має побічну дію, яка впливає на іншу частину, наприклад (з xвідключеною) echo $(echo foo >somefile)${x-$(cat somefile)}або echo $(echo $x),${x=1}.
Жиль

1
@Gilles; Я збентежений. Якщо підрозділ відрізняється від виконання сценарію, то чому так сказано: Запуск сценарію оболонки запускає новий процес, підрозділ. ? Також середовище додаткової оболонки має бути створене як дублікат середовища оболонки . Таким чином, ./file буде виконуватися в середовищі нижньої оболонки і, таким чином, він повинен успадковувати параметри оболонки, які встановлюються шляхом присвоєння змінної.
хакі

2
@haccks Визначення в ABS є приблизним, і не дуже хорошим. Приклади хороші, але перші два рядки цієї сторінки настільки спрощені, що вони помиляються. Запуск сценарію з іншого сценарію запускає новий процес, який не є передпластовою. У SUS визначення є правильними (але не завжди дуже зручними для розуміння). ./fileне виконується в допоміжній оболонці. Дивіться також unix.stackexchange.com/q/261638 та unix.stackexchange.com/a/157962
Gilles

15

Очевидно, що так, як говорить вся документація, в підпакеті виконується скобкована команда.

Підрозділ успадковує копію всіх батьківських змінних. Різниця полягає в тому, що будь-які зміни, внесені в нижню частину, також не вносяться в батьківську.

Сторінка ksh man робить це трохи зрозуміліше, ніж bash:

man ksh:

Команда, що сковується в дужках, виконується в підколонці без видалення неекспортованих змінних.

man bash:

(список)

список виконується в середовищі додаткової оболонки (див. КОМАНДУ ВИКОНАВАННЯ ЕКОЛОГІЇ нижче). Змінні призначення та вбудовані команди, які впливають на середовище оболонки, не залишаються в силі після завершення команди.

ЕКОЛОГІЧНЕ ВИКОНАННЯ

Оболонка має середовище виконання, яке складається з наступного: [...] параметрів оболонки, які встановлюються шляхом присвоєння змінної [...].
Підстановка команд, команди, згруповані з дужками, і асинхронні команди викликаються в середовищі підклітини, що є дублікатом оболонки, [...]


3
Цьому слід протиставити When a simple command other than a builtin or shell function is to be executed, it is invoked in a separate execution environment that consists of the following., що містить пункт: · shell variables and functions marked for export, along with variables exported for the command, passed in the environment(з того ж man bashрозділу), який пояснює, чому echo $x-script нічого не друкує, якщо xйого не експортують.
Йоган Е
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.