본문 바로가기
Dev/Shell

[Shell] source 와 sh 혹은 ./ 의 차이

by 생귄맨 2022. 12. 30.

missing-semester 의 두 번째 주제인 Shell Tools and Scripting의 문제들을 해결하던 중 여러 가지 난관에 봉착했다.

그 중 가장 핵심이 되는 sourcingexecuting의 차이를 짚고 넘어가는 것이 좋을 것 같아,

따로 정리한다.

 

문제를 같이 풀면서 해결하면 이해를 돕는 데에 더 좋을 것 같아 문제부터 보고가자.

marco.shpolo.sh 라는 두 가지 함수를 만들 것이다.

marco.sh 에서는 현재 디렉토리를 저장하는 함수를,

polo.sh 에서는 marco.sh 에서 저장된 현재 디렉토리의 경로로 이동하는 함수를 정의할 것이다.

 

  • marco.sh
#!/usr/bin/env sh
marco () {
  bar=$(pwd)
}

marco 라는 함수는 bar 라는 변수를 선언하고, 현재 디렉토리를 알려주는 pwd 프로그램의 출력값을 그대로 갖는다. 

  • polo.sh
#!/usr/bin/env sh
polo () {
  cd "$bar"
}

polo 라는 함수는 marco 에서 선언한 bar 라는 변수에 저장된 경로로 이동하는 역할을 수행한다. 


단순히 쉬운 문제 같지만, sourcingexecuting의 차이를 모른다면 해결하기 어렵다.

 

sourcing 부터 알아보자.

sourcing 은 말 그대로 현재 쉘 안에서 스크립트를 실행하는 것이다.

 

그러면 executing은 무엇일까?

 

흔히 executing의 예로 sh 와 ./가 있는데, sh는 sh 라는 프로그램을 실행시키고 인자로 스크립트를 넘겨주는 것이다. (스크립트를 실행시키는 것과 같은 뜻)

./ 도 비슷한데, 위 marco.sh와 polo.sh 상단에 전 포스트에서 다뤘던 shebang과 함께 어떤 인터프리터로 이 스크립트를 실행해야 하는지 명시되어 있기 때문에, sh marco.sh 나 ./marco.sh(with #!/usr/bin/env sh) 나 다를 바가 없다. 

 

executing은 새로운 subshell(현재 쉘 안에서 실행되는 또 다른 작은 쉘)을 열어 거기서 파일을 실행한다. 

따라서, subshell 에서 선언된 변수는 파일 실행이 끝나고, 현재 쉘로 돌아왔을 때는 없는 변수가 된다.

아래 실행 예시를 보자.

 

marco.sh를 executing 한 예시

 

분명 marco.sh 라는 스크립트 안에서 bar라는 변수를 선언했고, bar에는 현재 디렉토리의 경로가 값으로 할당되어 있어야 한다.

그런데, 보다시피 echo $bar를 하면 아무것도 출력이 되지 않는다.

 

그 이유는 바로 executing은 marco.sh를 현재 쉘이 아니라 subshell에서 실행했기 때문에 marco.sh 실행이 끝나는 순간, 즉 subshell이 닫히는 순간 bar 라는 변수는 사라지는 것이다. bar은 'subshell 안에서만' 유효했다. 

 

그렇다면 sourcing을 하면 어떨까?

marco.sh를 sourcing 한 예시

marco 라는 함수도 현재 쉘에서 잘 정의되어 있고, 함수를 실행하면 bar 라는 변수도 잘 선언되어 있는 것을 볼 수 있다.

현재 실행되고 있는 쉘 안에서 그대로 스크립트를 실행했기 때문에 파일 실행이 끝나도 그대로 변수와 함수가 유효한 것이다.

 

Q: 그러면 현재 쉘에서 변수와 함수는 언제까지 유효한 것인가요?

A: 지금 실행하고 있는 쉘을 닫고 다시 켜보시면 echo $bar를 했을 때 아무것도 출력되지 않을 것입니다. (직관적인 이해를 돕기 좋은 방법)
혹은, unset -f marco 와 unset bar를 통해 함수와 변수를 해제해주시면 됩니다. 

 


마치면서, 궁금증을 해결하는 것은 마치 지독하게 가렵던 곳을 시원하게 긁는 느낌같다.

최근에 missing-semester를 따라가며 shell을 배우고 있는데, 부딪치고 해결해가는 과정이 재밌고 유익하다.

더 많이 쩔쩔매고 고민할수록, 내 머릿속에 남는 것은 더 많아지는 것같다. 

계속해서 이런 방식으로 공부해야겠다.