Подтвердить что ты не робот

Передавать все переменные из одного shellscript в другой?

Итак, скажем, у меня есть shellscript/ bash script с именем test.sh

с:

#!/bin/bash
#

TESTVARIABLE=hellohelloheloo
./test2.sh

my test2.sh выглядит следующим образом

#!/bin/bash
#

echo ${TESTVARIABLE}

это не работает. Я не хочу передавать все переменные в качестве параметров, так как imho это перебор. Есть ли другой способ?

4b9b3361

Ответ 1

У вас есть в основном два варианта:

  • Внесите переменную переменную среды (export TESTVARIABLE) перед выполнением второго script.
  • Источник 2-го script, т.е. . test2.sh, и он будет работать в той же оболочке. Это позволит вам легко делиться более сложными переменными, такими как массивы, но также означает, что другой script может изменять переменные в исходной оболочке.

UPDATE:

Чтобы использовать export для установки переменной среды, вы можете либо использовать существующую переменную:

A=10
# ...
export A

Это должно работать как в bash, так и в sh. bash также позволяет комбинировать его так:

export A=10

Это также работает в моем sh (что бывает bash, вы можете использовать echo $SHELL для проверки). Но я не верю, что это гарантировано для работы во всех sh, поэтому лучше всего безопасно и отделить их.

Любая экспортируемая вами переменная будет видна в исполняемых сценариях, например:

a.sh:

#!/bin/sh

MESSAGE="hello"
export MESSAGE
./b.sh

b.sh:

#!/bin/sh

echo "The message is: $MESSAGE"

Тогда:

$ ./a.sh
The message is: hello

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

a.sh:

#!/bin/sh

MESSAGE="hello"
export MESSAGE
./b.py

b.py:

#!/usr/bin/python

import os

print 'The message is:', os.environ['MESSAGE']

Sourcing:

Вместо этого мы могли бы так выглядеть:

a.sh:

#!/bin/sh

MESSAGE="hello"

. ./b.sh

b.sh:

#!/bin/sh

echo "The message is: $MESSAGE"

Тогда:

$ ./a.sh
The message is: hello

Это более или менее "импортирует" содержимое b.sh напрямую и выполняет его в той же оболочке. Обратите внимание, что нам не нужно было экспортировать переменную для доступа к ней. Это неявно разделяет все переменные, которые у вас есть, а также позволяет другому script добавлять/удалять/изменять переменные в оболочке. Конечно, в этой модели оба ваших сценария должны быть одного языка (sh или bash). Чтобы привести пример, как мы могли передавать сообщения взад и вперед:

a.sh:

#!/bin/sh

MESSAGE="hello"

. ./b.sh

echo "[A] The message is: $MESSAGE"

b.sh:

#!/bin/sh

echo "[B] The message is: $MESSAGE"

MESSAGE="goodbye"

Тогда:

$ ./a.sh
[B] The message is: hello
[A] The message is: goodbye

Это одинаково хорошо работает в bash. Он также позволяет легко делиться более сложными данными, которые вы не могли бы выразить как переменную среды (по крайней мере, без какого-либо тяжелого подъема с вашей стороны), например массивы или ассоциативные массивы.

Ответ 2

Fatal Error предоставила прямую возможность: отправьте второй script! если вы опасаетесь, что этот второй script может изменить некоторые ваши драгоценные переменные, вы всегда можете указать его в подоболочке:

( . ./test2.sh )

Скобки заключают, что источник происходит в подоболочке, так что родительская оболочка не увидит изменений test2.sh.


Здесь также может быть указана другая возможность: используйте set -a.

В POSIX set ссылка:

-a: если этот параметр включен, атрибут экспорта должен быть установлен для каждой переменной, которой выполняется присвоение; см. раздел "Базовые определения" IEEE Std 1003.1-2001, Раздел 4.21 "Назначение переменных" . Если присваивание предшествует имени утилиты в команде, атрибут экспорта не должен сохраняться в текущей среде исполнения после завершения работы утилиты, за исключением того, что предшествующий одной из специальных встроенных утилит заставляет атрибут экспорта сохраняться после того, в завершена. Если присваивание не предшествует имени утилиты в команде или если задание является результатом работы утилит getopts или read, атрибут экспорта сохраняется до тех пор, пока переменная не будет отменена.

В Bash Руководстве:

-a: Отметьте переменные и функцию, которые были изменены или созданы для экспорта в среду последующих команд.

Итак, в вашем случае:

set -a
TESTVARIABLE=hellohelloheloo
# ...
# Here put all the variables that will be marked for export
# and that will be available from within test2 (and all other commands).
# If test2 modifies the variables, the modifications will never be
# seen in the present script!
set +a

./test2.sh

 # Here, even if test2 modifies TESTVARIABLE, you'll still have
 # TESTVARIABLE=hellohelloheloo

Обратите внимание, что в спецификациях указывается только, что при set -a переменная отмечена для экспорта. То есть:

set -a
a=b
set +a
a=c
bash -c 'echo "$a"'

будет echo c, а не пустая строка, а b (т.е. set +a не отменит экспорт для экспорта и не сохранит значение присваивания только для экспортируемой среды). Это, конечно, самое естественное поведение.

Заключение: использование set -a/set +a может быть менее утомительным, чем экспорт вручную всех переменных. Он превосходит поиск второго script, поскольку он будет работать для любой команды, а не только тех, которые написаны на одном языке.

Ответ 3

На самом деле более простой путь, чем экспорт и отключение или поиск ресурсов (по крайней мере, в bash, если вы в порядке с передачей переменных среды вручную):

пусть a.sh be

#!/bin/bash
secret="winkle my tinkle"
echo Yo, lemme tell you \"$secret\", b.sh!
Message=$secret ./b.sh

и b.sh be

#!/bin/bash
echo I heard \"$Message\", yo

Наблюдаемый выход

[rob @Archie test] $./a.sh
Эй, лемм, скажи, что ты "подмигиваешь моему звонку", b.sh!
Я услышал "подмигиваю мой звон", лет

Магия лежит в последней строке a.sh, где Message, для только продолжительности вызова ./b.sh, устанавливается значение secret из a.sh. В принципе, это немного похоже на именованные параметры/аргументы. Более того, он работает даже с такими переменными, как $DISPLAY, который управляет запуском приложения X Server.

Помните, что длина списка переменных окружения не бесконечна. В моей системе с относительно ванильным ядром xargs --show-limits говорит, что максимальный размер буфера аргументов составляет 2094486 байт. Теоретически, вы используете сценарии оболочки неправильно, если ваши данные больше, чем это (трубы, кто-нибудь?)

Ответ 4

Добавление к ответу Fatal Error, есть еще один способ передать переменные в другую оболочку script.

Вышеупомянутое предлагаемое решение имеет некоторые недостатки:

  • using Export: это приведет к тому, что переменная будет присутствовать вне их области действия, что не является хорошей практикой проектирования.
  • using Source. Это может вызвать конфликты имен или случайную перезапись предопределенной переменной в каком-то другом файле оболочки script, в котором есть другой файл.

Существует еще одно простое решение, которое мы можем использовать. Учитывая пример, опубликованный вами,

test.sh

#!/bin/bash

TESTVARIABLE=hellohelloheloo
./test2.sh "$TESTVARIABLE"

test2.sh

#!/bin/bash

echo $1

вывод

hellohelloheloo

Также важно отметить, что "" необходимы, если мы передаем многословные строки. Еще один пример

master.sh

#!/bin/bash
echo in master.sh
var1="hello world"
sh slave1.sh $var1
sh slave2.sh "$var1"
echo back to master

slave1.sh

#!/bin/bash
echo in slave1.sh
echo value :$1

slave2.sh

#!/bin/bash
echo in slave2.sh
echo value : $1

Выход

in master.sh
in slave1.sh
value :"hello
in slave2.sh
value :"hello world"

Это происходит из-за причин, которые точно описаны в этой ссылке

Ответ 5

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

#!/bin/bash

TESTVARIABLE=hellohelloheloo
(
export TESTVARIABLE    
source ./test2.sh
)

Преимущество заключается в том, что после запуска script из командной строки вы не увидите пропущенную в вашей среде $TESTVARIABLE:

$ ./test.sh
hellohelloheloo
$ echo $TESTVARIABLE
                            #empty! no leak
$

Ответ 6

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

A.bash:

#!/bin/bash
msg="The Message"
echo $msg > A.pipe

B.bash:

#!/bin/bash
msg=`cat ./A.pipe`
echo "message from A : $msg"

Использование:

$ mkfifo A.pipe #You have to create it once
$ ./A.bash & ./B.bash # you have to run your scripts at the same time

B.bash будет ждать сообщения, и как только A.bash отправит сообщение, B.bash продолжит работу.

Ответ 7

Другой вариант - использование eval. Это подходит только тогда, когда строки доверяют. Первый script может повторять назначение переменных:

echo "VAR=myvalue"

Тогда:

eval $(./first.sh) ./second.sh

Этот подход представляет особый интерес, когда второй script, который вы хотите установить для переменных окружения, находится не в bash, и вы также не хотите, чтобы переменные export, возможно, потому, что они чувствительны, и вы не Не хочу, чтобы они сохранялись.