Допустим, у меня есть сценарий shell / bash test.sh
с именем :
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
Моя test2.sh
выглядит так:
#!/bin/bash
echo ${TESTVARIABLE}
Это не работает. Я не хочу передавать все переменные в качестве параметров, так как имхо это излишне.
Есть ли другой способ?
Ответы:
У вас есть в основном два варианта:
export TESTVARIABLE
) перед выполнением 2-го сценария.. test2.sh
и он будет работать в той же оболочке. Это позволит вам легко обмениваться более сложными переменными, такими как массивы, но также означает, что другой скрипт может изменять переменные в исходной оболочке.ОБНОВИТЬ:
Чтобы использовать
export
для установки переменной среды, вы можете использовать существующую переменную:Это должно работать в обоих
bash
иsh
.bash
также позволяет комбинировать его так:Это также работает в моем
sh
(что может бытьbash
, вы можете использоватьecho $SHELL
для проверки). Но я не верю, что это гарантированно сработает во всемsh
, поэтому лучше оберегать их и разделять их.Любая переменная, которую вы экспортируете таким образом, будет видна в выполняемых вами скриптах, например:
a.sh:
b.sh:
Затем:
Тот факт, что оба сценария оболочки также случайны. Переменные окружения могут быть переданы любому процессу, который вы выполняете, например, если вместо этого мы использовали python, он может выглядеть так:
a.sh:
b.py:
Sourcing:
Вместо этого мы могли бы получить такой источник:
a.sh:
b.sh:
Затем:
Это более или менее «импортирует» содержимое
b.sh
напрямую и выполняет его в той же оболочке . Обратите внимание, что нам не нужно было экспортировать переменную для доступа к ней. Это неявно разделяет все имеющиеся у вас переменные, а также позволяет другому сценарию добавлять / удалять / изменять переменные в оболочке. Конечно, в этой модели оба ваших сценария должны быть на одном языке (sh
илиbash
). Чтобы привести пример, как мы могли бы передавать сообщения туда и обратно:a.sh:
b.sh:
Затем:
Это работает одинаково хорошо в
bash
. Это также позволяет легко обмениваться более сложными данными, которые вы не могли бы выразить как переменную среды (по крайней мере, без некоторой тяжелой работы с вашей стороны), например, массивами или ассоциативными массивами.источник
Фатальная ошибка дала прямую возможность: запусти свой второй скрипт! если вы беспокоитесь, что этот второй скрипт может изменить некоторые из ваших ценных переменных, вы всегда можете получить его в подоболочке:
Скобки заставят источник происходить в подоболочке, так что родительская оболочка не увидит, какие изменения
test2.sh
могут быть выполнены.Есть еще одна возможность, на которую обязательно нужно ссылаться: использовать
set -a
.Из ссылки на POSIX
set
:Из руководства Bash :
Итак, в вашем случае:
Обратите внимание, что спецификации только указывают, что с
set -a
переменной помечен для экспорта. То есть:будет отображаться как эхо,
c
а не пустая строкаb
(то естьset +a
не отменяет пометки для экспорта и не «сохраняет» значение присваивания только для экспортируемой среды). Это, конечно, самое естественное поведение.Вывод: использование
set -a
/set +a
может быть менее утомительным, чем экспорт всех переменных вручную. Это лучше, чем поиск второго сценария, так как он будет работать для любой команды, а не только для тех, которые написаны на одном языке оболочки.источник
На самом деле существует более простой способ, чем экспорт и сброс или повторное использование источников (по крайней мере, в bash, если вы можете передавать переменные окружения вручную):
пусть будет
и б.ш быть
Наблюдаемый вывод
Магия находится в последней строке
a.sh
, гдеMessage
только для продолжительности вызова./b.sh
установлено значениеsecret
froma.sh
. По сути, это немного похоже на именованные параметры / аргументы. Более того, он даже работает для таких переменных, как$DISPLAY
, например , которые контролируют, на каком X сервере запускается приложение.Помните, что длина списка переменных среды не бесконечна. В моей системе с относительно ванильным ядром,
xargs --show-limits
говорит мне, максимальный размер буфера аргументов составляет 2094486 байт. Теоретически, вы используете неправильные сценарии оболочки, если ваши данные больше, чем эти (каналы, кто-нибудь?)источник
Добавление к ответу Fatal Error, есть еще один способ передать переменные в другой скрипт оболочки.
Выше предложенное решение имеет некоторые недостатки:
using Export
: Это приведет к тому, что переменная будет присутствовать вне их области, что не является хорошей практикой проектирования.using Source
Это может привести к конфликтам имен или случайной перезаписи предопределенной переменной в каком-либо другом файле сценария оболочки, который получил другой файл.Есть еще одно простое решение, доступное для нас. Учитывая приведенный вами пример,
test.sh
test2.sh
вывод
Также важно отметить, что
""
это необходимо, если мы пропустим несколько слов. Взять еще один примерmaster.sh
slave1.sh
slave2.sh
вывод
Это происходит из-за причин, точно описанных в этой ссылке
источник
source
на самом деле хорошая вещь. Что касается вашего беспокойства: случайная перезапись предопределенной переменной , вы всегда можете получить источник в подоболочке. Это полностью решает проблему.( . ./test2.sh )
. Скобки заставят Bash запустить его содержимое в подоболочке.В Bash, если вы экспортируете переменную в подоболочке, используя круглые скобки, как показано, вы избегаете утечки экспортируемых переменных:
Преимущество здесь в том, что после запуска сценария из командной строки вы не увидите, что $ TESTVARIABLE просочился в вашу среду:
источник
$
строка) никогда не увидит экспортированный$TESTVARIABLE
. Экспорт просто передает копию переменной любым последующим дочерним процессам. Невозможно передать переменные обратно по цепочке родительским процессам, кроме как путем сохранения значения в хранилище и последующего чтения этого хранилища в сценарии родительского процесса. Возможна передача во вторую копию родительского скрипта, но это не будет тем же процессом . Отличное объяснение можно найти здесь .Еще один вариант использования
eval
. Это подходит только в том случае, если строки являются доверенными. Первый скрипт может отображать назначения переменных:echo "VAR=myvalue"
Затем:
eval $(./first.sh) ./second.sh
Этот подход представляет особый интерес, когда второй сценарий, для которого вы хотите установить переменные среды, не находится в bash, и вы также не хотите
export
использовать переменные, возможно, потому что они чувствительны, и вы не хотите, чтобы они сохранялись.источник
Другой способ, который для меня немного проще - это использовать именованные каналы. Именованные каналы предоставляли способ синхронизации и отправки сообщений между различными процессами.
A.bash:
B.bash:
Использование:
B.bash будет ждать сообщения, и как только A.bash отправит сообщение, B.bash продолжит свою работу.
источник