태그 보관물: shell

shell

한 쉘 스크립트에서 다른 쉘 스크립트로 모든 변수를 전달 하시겠습니까?

쉘 / bash 스크립트가 있다고 가정 해 보겠습니다 test.sh.

#!/bin/bash

TESTVARIABLE=hellohelloheloo
./test2.sh

test2.sh모습은 다음과 같습니다.

#!/bin/bash

echo ${TESTVARIABLE}

작동하지 않습니다. imho 이것은 과잉이기 때문에 모든 변수를 매개 변수로 전달하고 싶지 않습니다.

다른 방법이 있습니까?



답변

기본적으로 두 가지 옵션이 있습니다.

  1. export TESTVARIABLE두 번째 스크립트를 실행하기 전에 변수를 환경 변수 ( )로 만드십시오 .
  2. 두 번째 스크립트의 소스를 지정하십시오. 즉 . 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 서버를 제어 하는와 같은 변수에서도 작동합니다 .secreta.sh$DISPLAY

환경 변수 목록의 길이는 무한하지 않습니다. 상대적으로 바닐라 커널이있는 시스템 xargs --show-limits에서 인수 버퍼의 최대 크기는 2094486 바이트입니다. 이론적으로 데이터가 그보다 큰 경우 셸 스크립트를 잘못 사용하고 있습니다 (파이프, 누구?)


답변

치명적 오류의 답변에 추가하여 변수를 다른 쉘 스크립트로 전달하는 방법이 하나 더 있습니다.

위의 제안 된 솔루션에는 몇 가지 단점이 있습니다.

  1. using Export : 변수가 범위를 벗어나는 원인이되므로 좋은 설계 관행이 아닙니다.
  2. 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"

이 링크에 적절하게 설명 된 이유 때문에 발생 합니다.


답변

Bash에서 표시된 것처럼 괄호를 사용하여 서브 쉘 내에서 변수를 내 보내면 내 보낸 변수가 누출되지 않습니다.

#!/bin/bash

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

여기서 장점은 명령 행에서 스크립트를 실행 한 후 $ TESTVARIABLE이 환경에 유출되지 않는다는 것입니다.

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


답변

다른 옵션은을 사용하는 것 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는 작업을 계속합니다.