2016-04-04 2 views
1

Я пытаюсь экспортировать переменную из одного сценария и использовать его в другом сценарии, но эта переменная не экспортируется, что проблема может бытьпеременные общего доступа между двумя независимыми сценариями оболочки

Рассмотрим это как script1

#!/bin/sh 
export x=19 
exit 0 

Рассмотрим это как Скрипт2

#!/bin/sh 
echo "x="${x} 
exit 0 

я их выполнение в виде двух независимых сценариев, как

desktop:~/Desktop/Trail_Programs$ sh script1.sh 
desktop:~/Desktop/Trail_Programs$ sh script2.sh 

и выход

desktop:~/Desktop/Trail_Programs$ sh script2.sh 
x= 
+1

Среди часто задаваемых вопросов в Stack Overflow ['bash' tag wiki] (http://stackoverflow.com/tags/bash/info) вы можете заметить http://stackoverflow.com/questions/17852111/unable- to-export-the-variable-through-script-file и http://stackoverflow.com/questions/4277665/how-do-i-compare-two-string-variables-in-an-if-statement-in- bash - оба эти вопроса очень распространены. – tripleee

+0

thanks @tripleee –

ответ

1

David C. Rankin's helpful answer объясняет, почему ваш код не работает.

Примечание:
Следующее решение следует использовать только в том случае изменения скриптов вы работаете не вариант (решение может также представлять интерес, если вы хотите узнать о поиске и одноранговой переменных окружения).
В противном случае см. Решения, обсуждаемые внизу.

Чтобы решить вашу проблему, вы можете попробовать следующее:

x=$(trap 'printf %s "$x"' EXIT; . script1.sh >/dev/null) sh script2.sh 

Заметим, однако, что:

  • script1.sh будет - по необходимости - быть выполнена вашим текущей оболочки , который может быть или не быть sh.
  • script1.sh Выход выходного сигнала STDUT подавляется, поскольку должно быть обеспечено, что printf %s "$x" является единственным выходом стандартного вывода, созданным подоболочкой внутри подстановки команд ($(...)).
  • Этот подход ограничен переменной (хотя он может быть расширен для вывода значений нескольких переменных, которые вызывающий скрипт должен затем анализировать обратно на отдельные значения).

. script1.shисточники скрипт внутри подоболочки, что означает, что подоболочка выполняет script1.sh непосредственно в своей собственной среде, и поэтому видит переменные сценария после его выполнения (что означает, что он будет видеть $x, даже если бы не было экспорт).

trap 'printf %s "$x"' EXIT устанавливает выходную ловушку; то есть код, который выполняется, когда подоболочка выходит, в этом случае printf %s "$x", которая просто выводит значение интересующей переменной.
Обратите внимание, что этот подход необходим для обеспечения печати значения $x, даже если script1.sh прекращается из-за заявления exit; так как script1.sh находится в состоянии подзаголовком у подоболочки, exit выходит из всей подоболочки.

x=$(...) фиксирует это значение, и, будучи предваряется командовать sh script2.sh, эффективно делает полученную $xсреды переменную, которая script2.sh затем видит.


Это вообще проблематичен исходные сценарии, которые не были разработаны, чтобы быть получено:

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

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


Более надежные, универсальные решения (модификация сценариев требуется):

Имея сценарий, который устанавливает переменную окружения (ы) интересов сам вызвать другой сценарий является правильным решением , как показано в David's answer.

Если сценарии действительно должны работать как сверстники, значения должны быть переданы через файлов: есть сценарий, который устанавливает переменный (ы) интерес записывает свои значения в (временный) файл и имеют другие сценарий чтения файл:

script1.sh:

#!/bin/sh 
export x=19 
# Write to temp. file named for the *parent* process ID. 
# Since both script calls will have the same parent process, this 
# allows you to avoid a static filename subject to name collisions. 
printf %s "$x" > /tmp/x.$PPID 

script2.sh:

#!/bin/sh 
# Read the value of $x from the temp. file, then delete the file. 
x=$(cat /tmp/x.$PPID) && rm /tmp/x.$PPID 
echo "x=${x}" 
2

sourcescript1.sh от script2.sh.

В начале script2.sh (после притон), добавьте:

source /path/to/script1.sh 
+0

Хотя это может сработать в некоторых случаях, это, как правило, проблематично исходным скриптам, которые не были предназначены для источников. Помимо потенциально загрязняющих среду вызывающей оболочки, большая озабоченность вызывает операторы 'exit' в сценарии с исходным кодом (как показано в примерах сценариев OP), так как они неизбежно выходят из вызывающей оболочки сразу же. – mklement0

+0

@ mklement0 duh..missed 'exit'..anyway, первичная интуиция заключается в том, чтобы' source' второй скрипт в большинстве подобных случаев. – heemayl

0

Предположим, у вас есть файл tobeincluded1 с следующим содержанием

#this file tobeincluded1 will be included in master 
x=16 

и файл tobeincluded2 с следующим содержанием

#this file tobeincluded2 will be included in master 
y=21 

вы можете включить вышеуказанные файлы в свои s cript с использованием либо . или source, как показано ниже:

#!/bin/bash 

. ./tobeincluded1 #using the . to include a file 
source ./tobeincluded2 #using the source command to include a file 

echo "x : $x" 
echo "y : $y" 
2

Помните сценарий может НИКОГДА влияет окружение его родителя. NEVER средства NEVER. Так следуя правилу:

#!/bin/bash 
export x=19 
exit 0 

имеет NO воздействие на окружающую среду и не устанавливает x=anything там. export повлияет только на среду подоболочек, созданных в рамках этого скрипта. Например, возьмем сценарий, вызовите его exp.sh:

#!/bin/bash 
export x=19 
./script2.sh 
exit 0 

и script2.sh у вас есть:

echo "x = $x" 

Тогда, и только тогда, вы получите:

$ bash exp.sh 
x = 19 

Это просто правило ...

+1

++; но './script2.sh' не создает _subshell_, он создает процесс _child, который является оболочкой_. Экспортируемые переменные становятся переменными среды, которые видны для _any_ дочернего процесса, независимо от того, является ли это оболочкой или нет; Кроме того, я предлагаю сказать: «_cannot_ влияет на среду своего родителя». – mklement0

+0

Предположим, что я должен выполнить эти два сценария самостоятельно, нет родительских отношений между двумя сценариями, чем то, что я должен делать? –

+0

Вы нарушаете правило. Когда вам нужно что-то установить в своей среде. вы ограничены '/ etc/profile' или'/etc/bashrc' или версиями в '$ HOME' (например,' ~/.bashrc'). Именно так работают оболочки Linux. Вы можете «исходный» код, содержащий переменные, в текущую оболочку/скрипт, но вы не можете воздействовать на родителя. Подумайте, где и как устанавливаются «PS1» и «PATH». Это причина. Вы всегда можете написать файл 'tmp' и прочитать это из' script2', вы просто не можете использовать среду. –

Смежные вопросы