Я пытаюсь реализовать свою собственную оболочку, основанную на поведении bash, и я заметил, что некоторые команды не работают с каналами,
например, если у меня есть: export AAA=test | cat
, например, эта команда не будет добавлять AAA к переменным среды, поэтому экспорт не работает,
но если я напишу: export | cat
, он напечатает переменную среды, так что здесь это похоже на работу экспорта,
то же самое с выходом, неустановленным ....
так может ли кто-нибудь объяснить мне это поведение и как я могу его реализовать?
export
в обоих случаях выполняется в подоболочке, среда которой является копией родительской оболочки.
С помощью export | cat
вы копируете содержимое среды подоболочки, которое не было изменено из копии, полученной от родителя, поэтому вы получаете вывод, который соответствует тому, что мог бы получить только export
.
С помощью export AAA=test | cat
вы изменяете среду подоболочки, а не вызывающую оболочку. Кроме того, export
в этом случае не записывает никаких выходных данных для чтения cat
. После завершения конвейера подоболочка уничтожается, и управление возвращается к текущей оболочке, среда которой не была изменена.
я думаю, вы не поняли мой вопрос, проблема здесь в случае с каналом, экспорт ничего не добавит в переменную окружения моей оболочки, но в случае без канала он будет работать так, как ожидалось, так же, как и выход, если есть выход с пайпом, оболочка не выйдет.
@REVERSI, в канале или нет, export
не изменяет среду оболочки. Это влияет только на среду последовательно выполняемых команд.
@WilliamPursell Я думаю, это зависит от того, что вы подразумеваете под «окружающей средой». export AAA=test
обязательно устанавливает значение переменной с именем AAA
в test
в подоболочке. На самом деле нет никакой разницы (AFAIK) между переменными, инициализированными из родительской среды, и переменными, установленными позже. Это правда, что экспорт имени просто означает его пометку для использования при создании дочерней среды, а не запихивание переменной в какое-то отдельное пространство имен.
да, я знаю, это не изменит переменные среды родительской оболочки (bash), но изменит переменную среды моей оболочки. но мне просто нужно знать, почему он добавляет к переменной окружения подоболочки в случае без канала, и если есть канал, он не будет добавляться к переменной окружения подоболочки
@chepner Это верное замечание. Я думаю, что существует масса путаницы в отношении переменных и переменных среды, и, вероятно, лучше придерживаться точного определения «среды».
Я предполагаю, что в операционных системах есть существенное различие, которое ограничивает объем памяти, доступной для объединенной среды, и аргументы для новой команды.
@REVERSI Большинство оболочек реализуют конвейеры, разветвляя новые процессы для каждой команды. Некоторые оболочки (включая bash
, если установлена опция lastpipe
) будут выполнять последнюю команду в текущей оболочке. Я не знаю ни одной оболочки, которая будет выполнять любую другую команду в текущей оболочке, хотя я не верю, что POSIX на самом деле запрещает это.
@chepner Большое спасибо, это то, что я искал
Незначительная загвоздка:
export AAA=test | cat
на самом деле не изменяет среду подоболочки. Если эта подоболочка породила другую подоболочку, среда этой подоболочки будет иметь AAA в своей среде, но подоболочка, выполняющая командуexport
, не имеет измененной среды.