Захват определенной переменной среды из суб-оболочки Linux

740
NerdPirate

Я пытаюсь найти способ запустить сценарий оболочки B из сценария A, установить или экспортировать переменную в сценарии B и сохранить это значение в сценарии A после того, как сценарий B завершится и его суб-оболочка вернется.

Я не пытаюсь использовать сценарий B. Я хочу только одну конкретную переменную. Я могу добавить что-то в сценарий A, но я не хочу, чтобы какие-либо переменные, заданные в сценарии B, могли перезаписывать что-либо в сценарии A, кроме того, что я специально пытаюсь записать.

Я уверен, что есть несколько уродливых способов, например, записать все переменные, которые мне нужны в A, в файл, исходный скрипт B, затем прочитать все обратно из файла и восстановить переменные в A, кроме набора переменных в B что я хочу. Я ищу относительно чистый и простой способ, если таковой существует.

2
«Я не хочу, чтобы какие-либо переменные, заданные в сценарии B, могли перезаписывать что-либо в сценарии A, кроме того, что я специально пытаюсь записать» - переменные, заданные в сценарии B (в подоболочке), не будут перезаписывать никакие переменные в A. процессы не могут записывать в переменные окружения своего родительского процесса. Вам нужно будет специально захватить их. Roger Lipscombe 5 лет назад 0
Именно ... это то, что я хочу сделать. Я хочу специально их запечатлеть, как в заголовке моего вопроса. Мое заявление было направлено на то, чтобы предотвратить предложения сценария Б. NerdPirate 5 лет назад 0

2 ответа на вопрос

5
Ipor Sircer

Запишите эту конкретную переменную в стандартный вывод, затем в A:

specificvariable=$(/path/to/B.sh) 
Тем не менее, несколько замечаний (в основном для неопытных пользователей): (1) здесь запускается `B.sh`, поэтому вы запускаете всю команду вместо единственного` B.sh`, а не дополнительно. (2) Это будет захватывать весь вывод из `B.sh`, поэтому, если сценарий записывает больше требуемой переменной, решение не может быть легко применено. // Если вы хотите, вы можете ассимилировать мои замечания в ответ как свои собственные (т.е. без упоминания моего вклада); Я думаю, что это сделало бы ответ еще лучше. Kamil Maciorowski 5 лет назад 3
Это хороший вариант, но не для моего варианта использования, так как B.sh потенциально генерирует другой вывод. Но это хороший ответ для других людей, которые сталкиваются с этим вопросом. Спасибо NerdPirate 5 лет назад 0
3
Kamil Maciorowski

Этот другой ответ хорош, он должен быть вашим первым выбором, особенно если ваш B-скрипт делает одно и делает это хорошо (см. Философию Unix ), и эта «одна вещь» означает «вычисление этого конкретного значения переменной».

Но что, если основная цель B - напечатать что-то еще? или вообще взаимодействовать с пользователем? Передача дополнительных данных через стандартный вывод требует дополнительного анализа полученного результата. Если это так, совершенно независимый канал связи между B и A крайне желателен. В вашем случае достаточно односторонней связи.

Временный файл на самом деле очень хорош для этого. Но когда вы говорите

уродливые способы, такие как запись всех переменных, которые мне нужны в A, в файл, исходный сценарий B, затем чтение всех данных из файла и восстановление переменных в A, кроме набора переменных в B, который я хочу

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

В:

tmpf_foo=$(mktemp) 

Затем вы вызываете B "$tmpf_foo"в качестве аргумента командной строки и обращаетесь к файлу по "$1"B (или по другому номеру, в зависимости от дизайна). Это может быть не удобно, если B уже анализирует свои аргументы командной строки.

Альтернативный способ заключается в том, чтобы export tmpf_fooв A и обратиться к файлу, как "$tmpf_foo"в B.

Если B - инструмент общего назначения, который можно использовать не только изнутри A, хорошо проверить (в B), существует ли файл, прежде чем писать в него (например if [ -f "$tmpf_foo" ]; then …).

В любом случае, в B вы записываете желаемое значение в файл. Например, содержимое файла будет:

12345 

После успешного завершения B, в A вы получаете значение следующим образом:

specificvariable=$(<"$tmpf_foo") 

(эквивалентно, specificvariable=$(cat "$tmpf_foo")но без cat; не переносимо, хотя).

Если вам нужно передать более одной переменной из B в A, вы можете использовать несколько строк и читать их (в A) с помощью read. Но если вы заранее не знаете, какую переменную (и) следует изменить (или вообще не нужно изменять), то заставьте B создавать строки в файле, чтобы он выглядел так:

specificvariable=12345 othervariable="xyz 0" bar=baz unset var1 

После успешного завершения B в A вы получаете файл:

. "$tmpf_foo" 

Обратите внимание, что вы можете передать любую команду таким образом (в приведенном выше примере unsetэто команда), и она будет выполнена изнутри A. По этой причине вы должны быть очень осторожны при записи в файл изнутри B, и вы должны убедиться, что никакая другая ( мошенник) процесс может вставлять строки в файл.

В конце (в A) вы удаляете временный файл с помощью rm "$tmpf_foo".

О, мне это нравится. Экспорт временного файла прекрасно подходит для моего случая использования. Спасибо! NerdPirate 5 лет назад 0

Похожие вопросы