쉘 / bash 스크립트가 있다고 가정 해 보겠습니다 test.sh
.
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
내 test2.sh
모습은 다음과 같습니다.
#!/bin/bash
echo ${TESTVARIABLE}
작동하지 않습니다. imho 이것은 과잉이기 때문에 모든 변수를 매개 변수로 전달하고 싶지 않습니다.
다른 방법이 있습니까?
쉘 / bash 스크립트가 있다고 가정 해 보겠습니다 test.sh
.
#!/bin/bash
TESTVARIABLE=hellohelloheloo
./test2.sh
내 test2.sh
모습은 다음과 같습니다.
#!/bin/bash
echo ${TESTVARIABLE}
작동하지 않습니다. imho 이것은 과잉이기 때문에 모든 변수를 매개 변수로 전달하고 싶지 않습니다.
다른 방법이 있습니까?
답변:
기본적으로 두 가지 옵션이 있습니다.
export TESTVARIABLE
두 번째 스크립트를 실행하기 전에 변수를 환경 변수 ( )로 만드십시오 .. test2.sh
, 동일한 쉘에서 실행됩니다. 이렇게하면 배열과 같이보다 복잡한 변수를 쉽게 공유 할 수 있지만 다른 스크립트는 소스 셸에서 변수를 수정할 수 있습니다.최신 정보:
사용하려면 export
환경 변수를 설정하려면, 당신도 기존 변수를 사용할 수 있습니다 :
A=10
# ...
export A
이것은 모두에서 작동한다고 bash
하고 sh
. bash
또한 다음과 같이 결합 할 수 있습니다.
export A=10
이것은 또한 작동 내 sh
(될 일이있는 bash
, 당신이 사용할 수있는 echo $SHELL
체크). 그러나 나는 sh
그것이 모두 에서 작동한다고 보장하지 않으므로 안전하고 분리하는 것이 가장 좋습니다.
이 방법으로 내 보낸 변수는 다음과 같이 실행하는 스크립트에 표시됩니다.
금연 건강 증진 협회:
#!/bin/sh
MESSAGE="hello"
export MESSAGE
./b.sh
b.sh :
#!/bin/sh
echo "The message is: $MESSAGE"
그때:
$ ./a.sh
The message is: hello
이것들이 둘 다 쉘 스크립트라는 사실은 단지 부수적입니다. 환경 변수는 실행하는 모든 프로세스에 전달 될 수 있습니다. 예를 들어 파이썬을 대신 사용하면 다음과 같이 보일 수 있습니다.
금연 건강 증진 협회:
#!/bin/sh
MESSAGE="hello"
export MESSAGE
./b.py
b.py :
#!/usr/bin/python
import os
print 'The message is:', os.environ['MESSAGE']
소싱 :
대신 다음과 같이 소스를 사용할 수 있습니다.
금연 건강 증진 협회:
#!/bin/sh
MESSAGE="hello"
. ./b.sh
b.sh :
#!/bin/sh
echo "The message is: $MESSAGE"
그때:
$ ./a.sh
The message is: hello
이것은 다소간에 내용을 "가져 b.sh
와서 " 같은 쉘 에서 실행합니다 . 변수에 액세스하기 위해 변수를 내보낼 필요가 없습니다. 이것은 당신이 가진 모든 변수를 암시 적으로 공유하며, 다른 스크립트가 쉘에서 변수를 추가 / 삭제 / 수정할 수있게합니다. 물론이 모델에서 두 스크립트는 동일한 언어 ( sh
또는 bash
) 여야합니다 . 메시지를주고받을 수있는 방법을 예를 들어 보려면 :
금연 건강 증진 협회:
#!/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
. 또한 배열이나 연관 배열과 같이 환경 변수로 표현할 수없는 복잡한 데이터를 쉽게 공유 할 수 있습니다.
치명적 오류는 간단한 가능성을 제공했습니다. 두 번째 스크립트를 작성하십시오! 이 두 번째 스크립트가 귀중한 변수 중 일부를 변경할 수 있다고 걱정되면 언제든지 서브 쉘에서 소스를 사용할 수 있습니다.
( . ./test2.sh )
괄호는 소스가 서브 쉘에서 발생하도록하므로 부모 쉘은 수정 test2.sh
이 수행 될 수 있음을 알 수 없습니다 .
여기에서 분명히 참조해야 할 또 다른 가능성이 있습니다 : use set -a
.
로부터 POSIX의 set
참조 :
-a
:이 옵션이 켜져 있으면 할당이 수행되는 각 변수에 대해 내보내기 속성이 설정됩니다. IEEE Std 1003.1-2001, 섹션 4.21, 변수 할당 의 기본 정의 볼륨을 참조하십시오 . 할당이 명령에서 유틸리티 이름 앞에 오는 경우, 유틸리티가 완료된 후 내보내기 속성이 현재 실행 환경에서 지속되지 않습니다. 단, 내장 된 특수 유틸리티 중 하나가 내장 속성 이후에 내보내기 속성이 지속되는 경우는 예외입니다 . 에 완료되었습니다. 지정이 명령에서 유틸리티 이름 앞에 오지 않거나 지정이 getopts 또는 read 조작의 결과 인 경우 유틸리티의 경우 변수가 설정 해제 될 때까지 내보내기 속성이 유지됩니다.
로부터 배쉬 설명서 :
-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"'
c
빈 줄이 아니라 반향 되지 않으며 b
(즉, set +a
내보내기 표시를하지 않거나 내 보낸 환경에 대해서만 할당 값을 "저장"하지 않습니다). 물론 이것은 가장 자연스러운 행동입니다.
결론 : set -a
/ set +a
를 사용 하면 모든 변수를 수동으로 내보내는 것보다 지루할 수 있습니다. 동일한 쉘 언어로 작성된 명령뿐만 아니라 모든 명령에 대해 작동하므로 두 번째 스크립트 소싱보다 우수합니다.
실제로 환경 변수를 수동으로 전달해도 괜찮다면 적어도 bash에서 내보내고 설정을 해제하거나 소싱하는 것보다 쉬운 방법이 있습니다.
a.sh를 보자
#!/bin/bash
secret="winkle my tinkle"
echo Yo, lemme tell you \"$secret\", b.sh!
Message=$secret ./b.sh
그리고 b.sh
#!/bin/bash
echo I heard \"$Message\", yo
관찰 된 출력은
[rob @ Archie test] $ ./a.sh
Yo, lemme은 "내 윙클을 윙윙 거린다"고 말합니다. b.sh!
나는 "내 틴클을 흔들어"라고 들었어
마술은의 마지막 줄에 있으며 a.sh
, 여기서 Message
호출 기간 동안 만 from ./b.sh
값으로 설정됩니다 . 기본적으로 명명 된 매개 변수 / 인수와 약간 비슷합니다. 그러나 그 외에도 응용 프로그램이 시작되는 X 서버를 제어 하는와 같은 변수에서도 작동합니다 .secret
a.sh
$DISPLAY
환경 변수 목록의 길이는 무한하지 않습니다. 상대적으로 바닐라 커널이있는 시스템 xargs --show-limits
에서 인수 버퍼의 최대 크기는 2094486 바이트입니다. 이론적으로 데이터가 그보다 큰 경우 셸 스크립트를 잘못 사용하고 있습니다 (파이프, 누구?)
치명적 오류의 답변에 추가하여 변수를 다른 쉘 스크립트로 전달하는 방법이 하나 더 있습니다.
위의 제안 된 솔루션에는 몇 가지 단점이 있습니다.
using Export
: 변수가 범위를 벗어나는 원인이되므로 좋은 설계 관행이 아닙니다.using Source
: 다른 파일을 가져온 다른 셸 스크립트 파일에서 이름 충돌 또는 사전 정의 된 변수를 실수로 덮어 쓸 수 있습니다.우리가 사용할 수있는 또 다른 간단한 해결책이 있습니다. 귀하가 게시 한 예를 고려하면
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"
source
실제로 좋은 일이다. 걱정과 관련하여 : 사전 정의 된 변수를 실수로 덮어 쓰면 언제든지 서브 쉘을 사용할 수 있습니다. 문제를 완전히 해결합니다.
( . ./test2.sh )
. 괄호는 Bash가 서브 쉘에서 컨텐츠를 실행하게합니다.
Bash에서 표시된 것처럼 괄호를 사용하여 서브 쉘 내에서 변수를 내 보내면 내 보낸 변수가 누출되지 않습니다.
#!/bin/bash
TESTVARIABLE=hellohelloheloo
(
export TESTVARIABLE
source ./test2.sh
)
여기서 장점은 명령 행에서 스크립트를 실행 한 후 $ TESTVARIABLE이 환경에 유출되지 않는다는 것입니다.
$ ./test.sh
hellohelloheloo
$ echo $TESTVARIABLE
#empty! no leak
$
$
프롬프트)에는 내 보낸 내용 이 표시되지 않으므로 서브 쉘은 실제로 필요하지 않습니다 $TESTVARIABLE
. 내보내기 는 변수 의 사본 을 후속 하위 프로세스로 전달합니다. 스토리지에 값을 저장하고 나중에 상위 프로세스 스크립트에서 해당 스토리지를 읽는 경우를 제외하고 변수를 체인을 백업하여 상위 프로세스로 전달할 수 없습니다. 부모 스크립트의 두 번째 사본으로 파이핑 할 수는 있지만 동일한 프로세스 는 아닙니다 . 훌륭한 설명은 여기에서 찾을 수 있습니다 .
다른 옵션은을 사용하는 것 eval
입니다. 문자열을 신뢰할 수있는 경우에만 적합합니다. 첫 번째 스크립트는 변수 할당을 에코 할 수 있습니다.
echo "VAR=myvalue"
그때:
eval $(./first.sh) ./second.sh
인에 대한 두 번째 스크립트는 환경 변수를 설정하고자 할 때이 방법은 특히 흥미 롭다 하지 bash는 당신이 또한 싶지 않아 export
그들은 민감 아마도 때문에 변수와 당신이 그 (것)들을 유지하고 싶지 않아요.
조금 더 쉬운 또 다른 방법은 명명 된 파이프를 사용하는 것입니다. 명명 된 파이프는 서로 다른 프로세스간에 메시지를 동기화하고 보내는 방법을 제공했습니다.
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는 작업을 계속합니다.