Login vs Non-Login Shell
이번엔 좀 다른 관점에서 shell 이 실행되는 환경을 두가지로 나누어 볼 수 있습니다. 리모트 서버에 ssh 이나 telnet 으로 접속해서 login 과정을 거쳐 사용하게 되는 login shell 과 윈도우 매니저에서 메뉴로 제공하는 터미널 프로그램을 실행시켜 사용하게 되는 non-login shell 입니다.
login shell 인지 아닌지는
shopt -q login_shell; echo $?
을 통해 알아볼 수 있습니다.profile
,bashrc
등의 파일에는 사용자가 원하는 쉘 스크립트를 작성할 수 있습니다.
Login Shell
- 시작시
/etc/profile
,~/.bash_profile
,~/.bash_login
,~/.profile
순서로 파일을 읽어들여 실행합니다. 보통/etc/profile
에서는.
( source 명령 ) 을 이용해/etc/bash.bashrc
를 읽어들이고~/.profile
에서는~/.bashrc
파일을 읽어들입니다. (bash --login -c
와 같이 실행할 경우도 적용됩니다 ).
.profile 과 .bash_profile 두 가지가 존재하는 이유는
sh
과bash
를 구분하기 위해서 입니다. 가령 bash 가 사용될 경우 .bash_profile 파일이 존재하면 .profile 파일은 실행되지 않습니다.
logout ( 또는 exit ) 시에
~/.bash_logout
파일을 실행합니다.shopt -s huponexit
옵션 설정을 통해 logout 시에 background 로 실행되는 job 들에게 HUP 시그널을 보내 종료하게 할 수 있습니다.logout builtin 명령을 사용할 수 있습니다.
프롬프트 상에서
echo $0
를 실행했을때-bash
와같이 첫 문자가-
이면 login shell 을 나타냅니다.
Non-Login Shell
- 시작시
/etc/bash.bashrc
와~/.bashrc
파일을 실행합니다.
.rc 파일의 유래: 1965 년 MIT Compatible Time-Sharing System (CTSS) 에는 하나의 파일에 여러 명령을 넣어놓고 실행하는 기능이 있었는데 'run commands' 를 뜻하는 의미로 'runcom' 이라 불렀다고 합니다. 여기서 앞 글자를 따서 .rc 파일 이라고 합니다.
- non-login shell 에서도
bash -l
,sh -l
,sudo
,su
명령을 통해서 login shell 을 만들 수 있습니다.
$ shopt login_shell # 현재 터미널에서의 상태
login_shell off
$ echo $0
/bin/bash
$ sudo -i $ sudo -s $ su - mug896
# shopt login_shell # shopt login_shell Password: ******
login_shell on login_shell off $ shopt login_shell
# echo $0 # echo $0 login_shell on
-bash /bin/bash $ echo $0
-bash
$ bash --login
$ shopt login_shell
login_shell on
$ echo $0
bash
Real user id vs Effective user id
Real user id 는 시스템에 로그인했을 때의 id 를 말하며
$UID
readonly 환경 변수에 저장됩니다.
effective user id 는 set uid 비트가 설정된 프로그램을 실행했을 때 변경되며
$EUID
readonly 환경 변수에 저장됩니다.
$EUID
는 명령을 실행할 때 실질적인 권한에 해당합니다.
### alice 계정 ###
alice@box:/tmp$ cp /bin/bash bash
alice@box:/tmp$ chmod u+s bash # set uid 비트 설정
### bob 계정 ###
bob@box:/tmp$ ./bash -p
bash-4.3$ id # euid 가 alice 로 변경되었다
uid=1002(bob) gid=1005(gamers) euid=1004(alice) groups=1002(bob),1005(gamers)
.bashrc.d 만들어 사용하기
shell 을 사용하다 보면 내가 만든 함수, alias, 자동완성 이 쌓이게 되는데요.
이럴때 ~/.bashrc.d
디렉토리를 만들어서 한곳에서 관리하면 좋습니다.
이름 뒤에 .d
를 붙인것은 .bashrc 에서 사용하는 파일들이 위치하는 디렉토리 라는 뜻입니다.
# ~/.bashrc 에 들어갈 내용
# alias 설정 읽어들이기
for file in ~/.bashrc.d/aliases/*.sh
do
source "$file"
done
# 함수 설정 읽어들이기
for file in ~/.bashrc.d/functions/*.sh
do
source "$file"
done
# 자동완성 설정 읽어들이기
for file in ~/.bashrc.d/completions/*.sh
do
source "$file"
done
unset -v file
$PATH
환경 변수
$PATH
에 경로를 등록하면 명령을 실행시킬 때 따로 경로 지정없이 바로 파일 이름만
가지고 실행을 할 수가 있는데요. 만약에 동일한 이름의 명령이 두 곳의 디렉토리에
중복되어 나타날 경우 앞쪽에 등록한 디렉토리에 있는 명령이 우선순위를 갖게 됩니다.
명령 실행시 스크립트 내에서 설정되는
$0
변수의 값은선택된 경로 + 파일이름
이 됩니다.
Quiz
스크립트 파일은 외부에 파일로 존재하므로 ../../test.sh
, bin/test.sh
등과 같이
여러 가지 경로 지정 방법을 통해 실행시킬 수가 있습니다.
또한 symbolic link 로 연결될 수도 있는데요.
스크립트 내에서 자기 자신의 전체 경로와 physical 절대 경로를 구하려면 어떻게 할까요?
기본적으로
$PWD
와$0
를 합하면 전체경로가 됩니다.
#!/bin/sh
echo ' $0 : '"$0"
echo ' $PWD : '"$PWD"
echo '$( cd "${0%/*}/" && pwd -P ) : '"$( cd "${0%/*}/" && pwd -P )"
echo
echo " 스크립트 파일 전체경로 : $PWD/$0"
echo
echo " 스크립트 파일 절대경로 : $( cd "${0%/*}/" && pwd -P )/${0##*/}"
echo ' readlink -f $0 : '"$( readlink -f "$0" )"
------------------------------------------------------------------------
$ ln -s /usr/local/bin /home/mug896/foo # 홈 디렉토리에 foo 링크 생성
$ cp test.sh /home/mug896/foo/ # /usr/local/bin 으로 test.sh 파일 복사
$ cd /home/mug896/tmp # tmp 디렉토리로 이동해서 test.sh 실행
$ ../foo/test.sh
$0 : ../foo/test.sh
$PWD : /home/mug896/tmp
$( cd "${0%/*}/" && pwd -P ) : /usr/local/bin
스크립트 파일 전체경로 : /home/mug896/tmp/../foo/test.sh
스크립트 파일 절대경로 : /usr/local/bin/test.sh
readlink -f $0 : /usr/local/bin/test.sh
foo/../bar//./test.sh
와 같은 형태도 유효한 경로입니다.foo/../bar//./test.sh
--->foo/../bar/test.sh
--->bar/test.sh
가 된다.