Поиск по сайту:

Экспорт переменных в Bash: почему и как


Экспорт переменных в Bash; зачем это делается и как это можно сделать хорошо? Эта статья расскажет вам о подоболочках и продемонстрирует экспорт переменных Bash с ними, покажет вам, как экспортировать переменные и как избежать ошибок.

Экспорт переменных в Bash

При разработке более сложных сценариев в Bash, которые используют, например, подоболочку и многопоточные и/или фоновые настройки процессов, вам придется регулярно передавать переменные из основной оболочки в подоболочку. Именно в таких ситуациях становится интересным экспорт переменных оболочки.

Что такое подоболочка Bash?

Подоболочка Bash, или дочерняя оболочка, — это не что иное, как интерпретатор командной строки Bash (другими словами, оболочка Bash), перезапущенный изнутри. Таким образом, исходный процесс стал основным процессом, а второй процесс, который нужно запустить (тот, который запущен внутри главного или первого процесса), будет подоболочкой. Если основной процесс/оболочка завершится, то и подоболочка, работающая в нем, завершится.

Давайте сделаем это очень просто следующим образом:

bash
echo $$
ps -ef | grep -v grep | grep your_process_id

Казалось, ничего не произошло, когда мы набрали bash в терминале и нажали ввод. Однако в фоновом режиме был запущен новый процесс (подоболочка), и мы немедленно вступили в эту подоболочку.

Мы можем проверить то же самое, проверив, какие процессы активны. Во-первых, мы обнаруживаем PID (идентификатор процесса) нашей текущей (под-)шелла. Мы можем сделать это, проверив переменную $$ с помощью echo. PID — 362827. Затем мы можем составить список процессов с помощью ps -ef и исключить процесс grep из списка с помощью отрицания grep -v в | grep -v grep.

Мы обнаруживаем, что PPID (идентификатор родительского процесса) нашей подоболочки с PID 362827 равен 362815 (первый зеленый прямоугольник). PID (идентификатор процесса программы, указанный в конце строки) всегда отображается слева, тогда как идентификатор родительского процесса (PPID) всегда отображается справа. Это позволяет нам отступить настолько далеко, насколько мы можем или хотим идти.

Таким образом, мы обнаруживаем, что процесс 362815 (основной/родительский процесс, в котором размещается подоболочка 362827) принадлежит процессу 13185 (выделено белым цветом), и этот процесс идентифицируется последним ps как окно терминала, которое был запущен в среде рабочего стола. Он, в свою очередь, принадлежит гораздо ранее запущенному процессу 2184 (имя процесса здесь не показано) и т. д.

Таким образом, общая (видимая) иерархия составляет 2184 > 13185 (окно терминала) > 362815 (главная/основная оболочка внутри окна терминала) > 362827 (подоболочка запущена из оболочки Bash с идентификатором процесса 362815). Для более наглядного представления этой иерархии вы можете проверить команду/утилиту pstree, которая может потребовать установки в вашей операционной системе.

Чтобы узнать больше о Unix PID, см. Что такое Unix PID и как они работают? Энтони Хеддингс.

Важно понять, как работает иерархия Bash, поскольку она помогает нам понять, почему и где экспорт переменных становится интересным и часто необходимым.

Экспорт переменных в подоболочки

Есть много способов создать подоболочку. Один из способов — просто запустить подоболочку, как показано выше, набрав bash и выполнив дальнейшие команды на основе командной строки. Другой способ — запуск сеанса экрана GNU (см. Как использовать утилиту экрана GNU в Linux, если вы хотите узнать больше о экране GNU).

Вы также можете использовать идиому субшелла $ (здесь находится код подоболочки) непосредственно из командной строки и/или ваших сценариев Bash. Наконец, подоболочку можно запустить, просто поместив процесс в фоновый режим. Дополнительные сведения об управлении фоновыми процессами см. в разделе Управление фоновыми процессами Bash.

Итак, со всеми этими методами запуска подоболочек, как можно легко передавать переменные из одной оболочки в другую? Конечно, можно хранить переменные в файле (в любом формате), но это увеличит количество операций ввода-вывода и усложнит код Bash, который обрабатывает эту запись и чтение переменных.

Есть более простой способ. Вы можете думать об этом как о глобальных переменных в других языках программирования. Да, возможно, глобальные переменные избегают или не одобряют, но помните, что здесь мы имеем дело с отдельными процессами.

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

Синтаксис команды экспорта очень прост. Просто добавьте к назначению переменной команду export:

export A=1
B=2
bash
echo ${A}
echo ${B}

Здесь мы запускаем подоболочку и показываем, как переменная A была правильно передана в подоболочку с помощью команды export при ее определении. Мы также видим, что переменная B не перенесена в подоболочку, поскольку она была определена без использования export.

Свойство экспорта — это особое свойство, которое можно включать и выключать для данной переменной. Его легко включить, используя префикс команды export при определении переменной.

После установки такого свойства оно остается активным. Это то, на что следует обратить внимание при кодировании, поскольку это может привести к запутанным результатам, если кто-то не знает специфику этой операции. Легко предположить, что кто-то «повторно использует» переменную с тем же именем или даже случайно использует похожее имя переменной из разных сценариев в подоболочке и т. д. Давайте рассмотрим пример:

export C=1
export D=
D=1
bash
echo ${C}
echo ${D}

В этом примере мы видим, что переменная D сохраняет свое свойство экспорта даже при повторном назначении без явной команды export, и ее значение правильно передается подоболочке.

Свойство экспорта также можно удалить или отключить для переменной с помощью параметра -n для экспорта. Однако, чтобы быть эффективным, это нужно делать из основной/основной оболочки, а не из подоболочки:

export -n D
echo ${D}
exit
echo ${D}
bash
echo ${D}

Этот пример продолжается с последнего (т.е. все еще из активной подоболочки). Мы пытаемся удалить свойство export из переменной D, а затем выйти из подоболочки с помощью exit. Мы видим, что при возврате в основную оболочку наша переменная D сохранила свое значение, и это значение сохраняется при повторном входе в новую подоболочку. Таким образом, как видно, свойство экспорта не может быть удалено из переменной внутри подоболочки, если этой переменной было присвоено свойство экспорта в основной/главной оболочке.

Это похоже на другие методы кодирования Bash: подоболочка не может влиять на главную/основную оболочку. Это также имеет смысл с точки зрения безопасности во многих случаях, и безопасность, вероятно, является причиной, по которой разработчики Bash решили реализовать это таким образом. Давайте сделаем еще один шаг вперед и удалим свойство export из основной/родительской оболочки:

exit
export -n D
bash 
echo ${D}

Здесь мы выходим из подоболочки, только что созданной в последнем примере, а затем сбрасываем свойство export из переменной D. Затем мы повторно вводим подоболочку, аналогичную нашему последнему примеру, и видим, что наша переменная D пуста, так как она больше не экспортировалась в подоболочку. Вы также можете запустить export -p, чтобы увидеть все переменные экспорта. Переменные, которые вы экспортировали, вероятно, находятся в верхней части этого списка.

export -p | head -n1

Заключение

Изучив подоболочки и их связь с экспортом переменных Bash, мы далее привели пример экспорта переменных Bash. Мы рассмотрели различные способы экспорта переменных, а также метод очистки свойства export от переменных. Мы также увидели подвох, который может возникнуть, если вы повторно используете имена переменных. Наслаждайтесь экспортом!