bash에서“.”과“source”사이에 차이점이 있습니까?


37

"."의 차이점을 찾고있었습니다. "source"내장 명령과 몇 가지 소스 (예 : 설명 및 bash 맨 페이지)는 이들이 동일하다는 것을 나타냅니다.

그러나 환경 변수 문제로 테스트를 수행했습니다. 다음 testenv.sh을 포함 하는 파일 을 만들었습니다 .

#!/bin/bash
echo $MY_VAR

명령 프롬프트에서 다음을 수행했습니다.

> chmod +x testenv.sh
> MY_VAR=12345
> ./testenv.sh

> source testenv.sh
12345
> MY_VAR=12345 ./testenv.sh
12345

[첫 번째 양식은 빈 문자열을 반환했습니다.]

따라서이 작은 실험은 결국 "source"명령의 경우 자식 환경이 부모 변수의 모든 변수를 상속받는 곳인 "."위치에 차이 있음을 시사합니다 . 그렇지 않습니다.

뭔가 빠졌 습니까? 아니면 bash 의 문서화되지 않거나 사용되지 않는 기능 입니까?

[GNU bash, 버전 4.1.5 (1)-릴리스 (x86_64-pc-linux-gnu)]

답변:


67

짧은 답변

귀하의 질문에, 두 번째 명령은 .쉘 내장이나 내장을 사용하지 않습니다 source. 대신 실제로 다른 실행 파일과 마찬가지로 이름으로 스크립트 를 호출하여 별도의 쉘에서 스크립트 를 실행하고 있습니다. 이렇게하면 별도의 변수 세트가 제공됩니다 ( 부모 쉘에서 변수 내 보내면 모든 자식 프로세스의 환경 변수가 되므로 자식 쉘의 변수에 포함됩니다 ). 를 /공백으로 변경하면 .내장 기능으로 실행 됩니다 source.

확장 설명

이것은 source셸 내장 구문으로, 현재 셸에서 스크립트의 내용을 실행합니다 (따라서 현재 셸 변수로).

source testenv.sh

.내장 구문은 다음과 같은 기능을 수행합니다 source.

. testenv.sh

그러나이 구문은 스크립트를 실행 파일로 실행하여 새 셸을 실행하여 실행합니다.

./testenv.sh

.내장 되어 있지 않습니다 . 오히려, .실행중인 파일 경로의 일부입니다. 일반적으로, 적어도 하나의 /문자 를 포함하는 이름으로 호출하여 실행 파일을 쉘에서 실행할 수 있습니다 . 따라서 현재 디렉토리에서 파일을 실행하는 ./것이 가장 쉬운 방법입니다. 현재 디렉토리가에 있지 않으면 PATH명령을 사용하여 스크립트를 실행할 수 없습니다 testenv.sh. 이는 사람들이 시스템 명령이나 PATH환경 변수에 나열된 일부 디렉토리에 존재하는 다른 파일을 실행하려고 할 때 실수로 현재 디렉토리에서 파일을 실행하지 못하게하기위한 것입니다 .

(오히려보다 이름의 파일 실행 이후 source또는 .) 새로운 쉘에서 실행, 그것은 쉘 변수의 자신의 세트가됩니다. 새 쉘 호출 프로세스 (이 경우 대화식 쉘)에서 환경 변수를 상속받으며 해당 환경 변수는 새 쉘에서 쉘 변수가됩니다. 그러나 쉘 변수를 새 쉘로 전달하려면 다음 중 하나에 해당해야합니다.

  1. 쉘 변수가 익스포트되어 환경 변수가되었습니다. 이를 위해 export쉘 내장을 사용하십시오 . 예를 들어, export MY_VAR=12345한 단계에서 변수를 설정하고 내보내는 데 사용할 수 있으며 이미 설정되어 있으면 간단히 사용할 수 있습니다 export MY_VAR.

  2. 쉘 변수는 명시 적으로 설정되어 실행중인 명령에 전달되어 명령이 실행되는 동안 환경 변수가됩니다. 이것은 일반적으로 다음을 수행합니다.

    MY_VAR=12345 ./testenv.sh

    경우 MY_VAR수출되지 않은 쉘 변수이다, 당신도 실행할 수 있습니다 testenv.shMY_VAR의해 환경 변수로 전달 자체로 설정 :

    MY_VAR="$MY_VAR" ./testenv.sh

./ 스크립트 구문이 제대로 작동하려면 Hashbang 줄이 필요합니다

그건 그렇고, 위와 같이 ( .또는 source내장 쉘이 아닌) 이름으로 실행 파일을 호출 할 때 실행하는 데 사용되는 쉘 프로그램은 일반적으로 실행중인 쉘에 의해 결정 되지 않습니다. . 대신 :

  • 바이너리 파일의 경우, 커널은 특정 유형의 파일을 실행하도록 구성 될 수 있습니다. 파일의 처음 2 바이트 에서 이진 실행 파일의 종류를 나타내는 "마법 번호" 를 검사합니다 . 실행 바이너리를 실행할 수있는 방법입니다.

    물론 실행 가능한 바이너리 인 쉘이나 다른 인터프리터 없이는 스크립트를 실행할 수 없기 때문에 이것은 매우 중요합니다! 또한 많은 명령과 응용 프로그램은 스크립트가 아니라 컴파일 된 바이너리입니다.

    ( #!텍스트 실행 파일을 나타내는 "마법 번호"의 텍스트 표현입니다.)

  • 쉘 또는 다른 해석 언어로 실행되는 파일의 경우 첫 번째 행은 다음과 같습니다.

    #!/bin/sh

    /bin/sh프로그램을 실행하기 위해 다른 쉘이나 인터프리터로 대체 될 수 있습니다. 예를 들어, 파이썬 프로그램은 다음 줄로 시작할 수 있습니다.

    #!/usr/bin/python

    이 줄을 hashbang, shebang 및 기타 여러 유사한 이름이라고합니다. 이 FOLDOC 항목 , Wikipedia 기사#! / bin / sh를 통역사가 읽습니까? 자세한 내용은.

  • 텍스트 파일이 실행 가능 으로 표시되어 있고 셸 (예 :)에서 실행 ./filename하지만로 시작 하지 않으면#! 커널이이를 실행하지 못합니다. 그러나이 일어난 것을보고, 쉘이됩니다 시도 에 이름을 전달하여 실행하는 일부 쉘. 어떤인지 에 대한 요구 사항거의 없습니다 ( "쉘은 쉘을 호출하는 것과 동등한 명령을 실행해야합니다 ..." ). 실제로 *를 포함한 일부 쉘 은 다른 인스턴스를 실행 하지만 다른 쉘 은bash/bin/sh. 나는 이것을 피하고 대신 hashbang 라인을 사용하는 것이 좋습니다 (또는 원하는 인터프리터 (예 :)에 스크립트를 전달하여 실행하십시오 bash filename).

    * 수동 GNU 배쉬 , 3.7.2 명령 검색 및 실행 : "파일이 실행 파일 형식이 아닌, 파일이 디렉토리는,로 가정하지 않기 때문에이 실행이 실패하면 쉘 스크립트 설명과 쉘이 실행을 에서 쉘 스크립트 . "


2
내가 유용하게 찾은 것은 source다시로드하거나 다시 시작할 필요없이 bash에서 함수를 사용할 수 있다는 것입니다. 예 #!/bin/bash function olakease {echo olakease;}. 당신이 그것을로드하면 bash에서 source file.sh직접 호출 할 수 있습니다 olakease. 정말 좋아합니다. 소스는 많은 것들을 .실행하고 , 점 은 실행만을위한 bash file.sh
것이고

2
@ erm3nda은 .뿐만 아니라이 동작을 가지고 . file.shsource file.sh에 정의 된 고정 기능을 포함 정확히 같은 일을 수행합니다 file.sh. (아마도 당신 ./file.sh은 다른 생각을 하고 있습니다. 그러나 그것은 내장을 사용 하지 않습니다. ; 대신에 .경로의 일부입니다.)
Eliah Kagan

오!, 나는. [space] 파일을주의 깊게 읽지 않았다. 정말 감사합니다.
erm3nda

13

네, 뭔가 빠졌습니다.

나는 당신이 '.'을 혼동하고 있다고 생각합니다. 이는 현재 디렉토리를 의미 ./testenv.sh하며 '.' 그것은 source(내장 명령 인)을 의미합니다. 따라서 '.' 의미 source가 될 것이다 . ./testenv.sh. 말이 되나요?

따라서 이것을 시도하십시오 :

MY_VAR=12345 
. ./testenv.sh

2
./파일은 파일이없는 파일의 위치를 ​​알려주며 bash는 먼저 PATH를 찾은 다음 현재 디렉토리를 찾지 못하면 시도합니다. bash가 POSIX 모드에서 실행 중이고 파일과 같은 경로를 제공하지 않으면 (예 ./:), PATH에서만 검색하고 현재 디렉토리가 PATH에 없으면 파일을 찾지 못합니다.
geirha

@geirha 네, 맞습니다 source(그리고 .)는 실제로 일반적인 의미에서 스크립트를 실행 하지 않더라도 실제로 $ PATH를 먼저 확인 합니다. 내 (이전) 의견이 잘못되었습니다.
Eliah Kagan

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