어떤 SHELL을 사용하고 있는지 확인해보자.
어러 쉘이 있다. sh(Bourne Shell)을 기반으로 하는 Bash(Bourne-again shell), zsh(Z shell) 등은 문법이 거의 똑같지만 완전히 같지는 않다.
쉘스크립트를 만들어 실행 하는 경우 #!
지시자로 사용할 쉘을 지정할 수 있기 때문에 크게 문제가 없지만 source
명령이나 dot
(.
) 명령으로 현재 환경(Current Environment Context)에서 스크립트를 실행하는 경우 사용중인 쉘의 종류에 따라 문법이 달라 문제가 발생 할 수 있다. 주의해서 처리 하도록 하자.
기본쉘을 Zsh 사용하기 시작하면서 겪은 문제다. 보통 리눅스에서 기본쉘은 Bash 이기 때문에 거의 모든 프로그램들이 Bash 위주로 구현되어 있기 때문에 발생 하는 문제이다.
대부분 다음과 같은 문제이다.
실행 스크립트의 파일 이름을 알고 싶을때 Bash에서는 $BASH_SOURCE
를 사용한다. 하지만 이 변수는 Bash 에서만 지원됨으로 Zsh에서는 $0
변수를 사용해야 된다. Bash에서도 $0
변수를 지원하지만 Bash에서 $0
변수를 사용하면 쉘의 정보((bash
)가 표시된다.
쉘스크립트에서
$0
는 실행파일의 이름을 나타내는 변수 이다. Bash에서$0
변수는 쉘이 시작할 때만 초기화 되지만dot
명령은 새로운 쉘을 시작하는 것이 아니라 현재 쉘의 컨텍스트에서 실행 하는 것이므로 쉘에서echo $0
를 실행한것과 같은 결과(즉,bash
)가 출력된다. 그런데 Zsh 에서는$0
가 스크립트 이름으로 세팅된다.
구글링을 해보면 Zsh에서 Bash의
$BASH_SOURCE
와 가장 가까운 결과를 내는것은${(%):-%x}
라고 한다. 하지만$0
도 같은 결과는 내기 때문에 그냥 사용하기로 한다.
다음은 ./env
파일의 내용이다.
|
|
각 SHELL에서 실행 해 보자
. ./env
다음과 같은 출력을 얻을 수 있다.
bash
$BASH_SOURCE = ./env
$0 = bash
zsh
$BASH_SOURCE =
$0 = ./env
따라서 실행 되는 스크립트의 이름 알기 위해서는 다음과 같이 쉘에 따라 다른 방식을 정용하여야 한다.
SH_NAME=$(basename $(readlink /proc/$$/exe))
case ${SH_NAME} in
"zsh") SELF=$(realpath $0) ;;
"bash") SELF=$(realpath ${BASH_SOURCE[0]}) ;;
*) echo "Unknown SHELL $SH_NAME" && exit 0 ;;
esac
echo $SELF
Bash 또는 Zsh 만 사용한다면 다음과 같이 사용해도 같은 결과를 얻을 수 있다.
SELF=$(realpath ${BASH_SOURCE[0]:-$0})
echo $SELF
아래와 같이 env 파일을 만들고 dot command
로 실행해보자
SELF=${BASH_SOURCE[0]:-$_}
echo $(basename $SELF) is located at $(realpath $SELF)
env
파일 실행
. ./env
Bash, Zsh 둘다 같은 결과를 얻을 수 있다.
env is located at /home/euikook/src/env
$SHELL
/etc/password
파일에 정의된 사용자에 할당된 SHELL 출력한다.
echo $SHELL
Cons
지정된 쉘 정보를 표시 하지만 현재 사용중인 SHELL 정보를 출력하지 않는다.
$ cat /etc/passwd | grep $USER
john:x:1000:1000::/home/john:/usr/bin/zsh
cat
명령으로 /etc/passwd
파일을 확인 결과 /usr/bin/zsh 가 쉘로 할당되어 있다.
아래와 같이 bash
로 쉘을 변경 후 $SHELL
과 $0
정보를 출력 해보자.
$ bash
$ echo echo User SHELL is $SHELL, Current SHELL is $0
User SHELL is /usr/bin/zsh, Current SHELL is bash