Bash 스크립트 실행과 소싱의 차이점은 무엇입니까?


답변:


344

짧은 답변

스크립트를 소싱 하면 현재 쉘 프로세스 에서 명령이 실행 됩니다.

실행 스크립트 것은에서 명령이 실행됩니다 새로운 쉘 프로세스를.

스크립트가 현재 실행중인 쉘에서 환경을 변경하도록하려면 소스를 사용하십시오. 그렇지 않으면 실행을 사용하십시오.

여전히 혼란 스러우면 계속 읽으십시오.

술어

실행할 구문과 소스에 대한 구문에 대한 일반적인 혼동을 명확히하려면 다음을 수행하십시오.

./myscript

이것은 것입니다 실행 myscript 파일이 실행 가능한 것이어야한다 현재 디렉토리에 있습니다. 선행 점과 슬래시 ( ./)는 현재 디렉토리를 나타냅니다. 현재 디렉토리가 일반적으로에 있지 않기 때문에 필요합니다 $PATH.

myscript

이것은 것입니다 실행 myscript 파일이 실행하고있는 일부 디렉토리에있는 경우 $PATH.

source myscript

소스 myscript 입니다. 파일은 실행 파일 일 필요는 없지만 유효한 쉘 스크립트 여야합니다. 파일은 현재 디렉토리 또는의 디렉토리에있을 수 있습니다 $PATH.

. myscript

이것도 소스가 myscript 됩니다. 이 "맞춤법"은 POSIX에서 정의한 공식적인 것 입니다. source점에 대한 별칭으로 정의 된 배쉬 .

데모

myscript.sh다음 내용을 고려하십시오 .

#!/bin/sh
# demonstrate setting a variable
echo "foo: "$(env | grep FOO)
export FOO=foo
echo "foo: "$(env | grep FOO)
# demonstrate changing of working directory
echo "PWD: "$PWD
cd somedir
echo "PWD: "$PWD

스크립트를 실행하기 전에 현재 환경을 확인하십시오.

$ env | grep FOO
$ echo $PWD
/home/lesmana

변수 FOO가 정의되어 있지 않으며 홈 디렉토리에 있습니다.

이제 파일 을 실행 합니다 :

$ ./myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

환경을 다시 확인하십시오.

$ env | grep FOO
$ echo $PWD
/home/lesmana

변수 FOO가 설정되지 않았고 작업 디렉토리가 변경되지 않았습니다.

스크립트 출력은 변수가 설정되었고 디렉토리가 변경되었음을 명확하게 보여줍니다. 나중에 확인하면 변수가 설정되지 않고 디렉토리가 변경되지 않은 것으로 나타납니다. 어떻게 된 거예요? 새로운 쉘 에서 변경되었습니다 . 현재 쉘은 양산 새로운 스크립트를 실행하는 쉘. 스크립트가 새 셸에서 실행 중이며 환경에 대한 모든 변경 사항이 새 셸에 적용됩니다. 스크립트가 완료되면 새로운 쉘이 파괴됩니다. 새 셸에서 환경에 대한 모든 변경 사항은 새 셸을 통해 삭제됩니다. 출력 텍스트 만 현재 쉘에 인쇄됩니다.

이제 파일 을 소싱 합니다 :

$ source myscript.sh
foo:
foo: FOO=foo
PWD: /home/lesmana
PWD: /home/lesmana/somedir

환경을 다시 확인하십시오.

$ env | grep FOO
FOO=foo
$ echo $PWD
/home/lesmana/somedir

변수 FOO가 설정되고 작업 디렉토리가 변경되었습니다.

스크립트를 소싱해도 새 셸이 만들어지지 않습니다. 모든 명령은 현재 쉘에서 실행되며 환경 변경은 현재 쉘에서 적용됩니다.

이 간단한 예제에서 실행 결과는 스크립트 소싱과 동일합니다. 항상 그런 것은 아닙니다.

또 다른 데모

다음 스크립트를 고려하십시오 pid.sh.

#!/bin/sh
echo $$

(특수 변수 $$는 현재 실행중인 쉘 프로세스의 PID로 확장됩니다)

먼저 현재 쉘의 PID를 인쇄하십시오.

$ echo $$
25009

스크립트를 소싱하십시오.

$ source pid.sh
25009

스크립트를 실행하고 PID를 확인하십시오.

$ ./pid.sh
25011

다시 출처 :

$ source pid.sh
25009

다시 실행하십시오.

$ ./pid.sh
25013

스크립트 실행이 동일한 프로세스에서 실행되는 동안 스크립트를 실행하면 매번 새 프로세스가 작성되는 것을 볼 수 있습니다. 이 새로운 프로세스는 스크립트 실행을 위해 만들어진 새로운 쉘입니다. 스크립트를 소싱해도 새 셸이 생성되지 않으므로 PID는 동일하게 유지됩니다.

요약

스크립트를 소싱하고 실행하면 마치 한 줄씩 명령을 입력 한 것처럼 한 줄씩 스크립트에서 명령이 실행됩니다.

차이점은 다음과 같습니다.

  • 셸을 여는 스크립트 를 실행할 셸에 명령을 입력하고 출력을 다시 현재 셸에 복사 한 다음 새 셸을 닫습니다. 환경에 대한 모든 변경 사항은 새 셸에서만 적용되며 새 셸을 닫으면 손실됩니다.
  • 스크립트 를 소싱 할 때 현재 쉘에 명령을 입력하는 것 입니다. 환경에 대한 모든 변경 사항이 적용되며 현재 셸에 유지됩니다.

스크립트가 현재 실행중인 쉘에서 환경을 변경하도록하려면 소스를 사용하십시오. 그렇지 않으면 실행을 사용하십시오.


또한보십시오:


2
소싱을 사용하는 것은 스크립트를위한 기본적인 형태의 구성 파일을 만드는 것입니다. 다양한 변수를 기본값으로 설정하여 시작한 다음 myscript.conf와 같은 소스를 사용하십시오. 소스 스크립트에는 원하는 값을 재정의하는 명령문이 있습니다. 소스 스크립트는 # / bin / bash로 시작하지 않으므로 직접 실행하지 않는 것이 좋습니다.
LawrenceC

소스는 전역 범위에서 실행하는 것과 비슷하며 실행하면 새로운 로컬 범위가 만들어집니다. 이것을 스크립트의 함수로 확장 할 수 있습니까? 함수를 (정상적으로) 실행하거나 "소스"하기 위해?
aliteralmind

2
사용 source myscript.sh과 차이점이 . myscript.sh있습니까?
Holloway

2
bash를 사용하면 실제로 아무런 차이가 없습니다. source는 bash에 표시 할 별칭입니다.
lesmana

1
나는 사람들이 그런 정교한 예제를 제공하여 나 같은 리눅스 초보자조차도 이해할 수 있기를 좋아합니다. 감사!
Julius

21

스크립트를 실행하면 별도의 자식 프로세스에서 실행됩니다. 즉, 스크립트를 처리하기 위해 별도의 쉘 인스턴스가 호출됩니다. 이는 스크립트에 정의 된 환경 변수 등을 상위 (현재) 셸에서 업데이트 할 수 없음을 의미 합니다.

스크립트를 소싱한다는 것은 현재 쉘 자체가 스크립트를 파싱하고 실행한다는 의미입니다. 마치 스크립트 내용을 입력 한 것과 같습니다. 이러한 이유로, 소스가되는 스크립트는 실행 가능할 필요가 없습니다. 그러나 물론 실행하려면 실행 파일이어야합니다.

현재 쉘에 위치 인수가 있으면 변경되지 않습니다.

그래서 내가 a.sh포함 된 파일이 있다면 :

echo a $*

그리고 나는 :

$ set `date`
$ source ./a.sh

나는 다음과 같은 것을 얻는다 :

a Fri Dec 11 07:34:17 PST 2009

그런데, ...한데:

$ set `date`
$ ./a.sh

나에게 준다 :

a

희망이 도움이됩니다.


5
이 대답은 모든면에서 정확하지만 다른 개념 (위치 매개 변수 설정)을 사용하여 시연되기 때문에 이해하기가 매우 어렵다는 것을 알고 있습니다. 소싱과 실행의 차이보다 훨씬 혼란 스럽습니다.
lesmana

9

소싱은 기본적으로 명령 프롬프트에서 스크립트의 각 줄을 한 번에 하나씩 입력하는 것과 같습니다 ...

실행은 새 프로세스를 시작한 다음 스크립트의 각 줄을 실행하여 현재 환경이 반환하는 내용 만 수정합니다.


6

또한, ./myscriptmyscript 파일에 대한 실행 권한이 필요한 스크립트를 실행하는 동안 소싱에는 실행 권한이 필요하지 않습니다. 그렇기 때문에 chmod +x myscript전에는 필요하지 않습니다source myscript


2
사실이지만 문제가 있으면 언제든지 실행할 수 있습니다 bash myscript.
Daniel Beck

5

소싱을 통해 스크립트에 정의 된 모든 추가 변수를 얻을 수 있습니다.
따라서 구성 또는 기능 정의가 있으면 소스를 작성하고 실행하지 않아야합니다. 실행은 부모 환경과 독립적입니다.


3

내가 올바르게 기억한다면, 스크립트를 실행하면 #!스크립트 파일과 함께 라인 에서 실행 파일을 인수로 실행합니다 (일반적으로 새로운 쉘을 시작하고 효과적으로 새로운 쉘에 스크립트를 소싱합니다 #!/bin/sh).
반면 스크립트를 소싱하면 현재 쉘 환경에서 각 행이 실행되므로 현재 쉘을 변경하는 데 유용합니다 (예 : 쉘 기능을 정의하고 환경 변수를 내보내는 방법 제공).


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.