shell script 파일 실행 시 . 실행 이유

kkb의 이미지

shell script 파일 실행 시 . 으로 실행시키는 이유가 무엇인가요?

다음과 같이 두 가지 방법으로 실행시킬 때 어떤 차이가 있나요?

$ . bash_script_file

$ ./bash_script_file

전자의 경우 current shell environment 환경변수가 적용된다는 거 같은데
후자도 current shell environment 환경변수가 적용되지 않나요?
두 가지 실행방법의 각 차이가 궁금합니다.

감사합니다.

Prentice의 이미지

다른 차이도 있겠지만 macOS의 예를 들어 보면, 내 시스템에 설치된 /bin/bash가 너무 오래된 3.2.57 버전일 때, 개인적으로 더 높은 5.2.2 버전을 따로 설치하고 ./bash_script_file의 시작 부분에서 #!/usr/local/bin/bash 이런 식으로 커스텀 경로를 지정해서 쓴다거나 할 수도 있습니다.

#!/usr/bin/env bash 이런 식으로 그냥 알아서(?) bash를 실행하게 만든 다음, 내가 바라는 bash 버전이 실행되게 $PATH 요소 순서를 지정해놓는 수도 있고요.

원글에서 예로 들어주신 전자의 경우 login shell을 그대로 쭉 쓰는 것이지만 후자의 경우 다른 shell을 쓸 수도 있습니다. 그냥 login shell 써도 되지만요.

Prentice의 이미지

원글 전자의 경우 현재의 셸에서 스크립트가 실행되는 반면, 원글 후자의 경우 자식인 서브셸에서 스크립트가 실행됩니다.

#!/usr/bin/env bash
export FOO="foo"
echo $FOO

요런 파일이 ./foo.sh로 있을 때,

$ ./foo.sh
foo
$ echo $FOO

$

Subshell 안에서 만들었던 $FOO는 부모 환경에는 영향을 끼치지 않았습니다.

$ . ./foo.sh
foo
$ echo $FOO
foo
$ 

. 통해서 현재 shell에서 실행하면 실제로 타자를 통해서 export FOO="foo"를 실행한 것처럼 현재 환경이 계속 영향을 받네요.

김정균의 이미지

bash 에서 '.' 은 bash 내부 명령어인 source 와 동일 합니다.
sh 에서는 source 를 사용하고, bash 에서 source 대선 '.' 을 지원하기 시작했습니다.

용도는 현재 쉘에 해당 파일을 include 한다는 개념으로 받아 들이시면 이해가 쉬울 것 같습니다. 환경 변수 뿐 아니라 function 이나 기타 bash 코드를 다 사용할 수 있습니다.

예를 들어,아래와 같이 bash function 을 bash 내부 명령어 처럼 사용할 수도 있습니다.
declare 내부 명령어로 현재 쉘에 등록되어 있는 함수도 알 수 있습니다.

[user@host ~]$ cat <<EOL > func.sh
function A {
    echo "AA"
}
EOL
[user@host ~]$ . ./func.sh
[user@host ~]$ A
AA
[user@host ~]$ declare -f A
function A {
    echo "AA"
}
[user@host ~]$

관련 메뉴얼은 man bash 하셔서 source 를 찾아보시면 되고, 영어가 부족하다고 생각 되시면, https://mug896.github.io/bash-shell/builtin_commands.html 의 제일 첫 부분이 '.' 에 대한 내용이 있으니 참고 하시면 되겠습니다.

kkb의 이미지

위에 답변주신 분들 모두 감사드립니다.
너무 재밌게 읽었습니다.