5.1 shell의 기능 shell이란 프로그램의 실행을 위한 인터페이스로, 사용자와 커널 사이에 정보를 전달해주는 역할을 한다. 사용자가 특정 명령어를 입력하면 우선 쉘이 접수하여 그 내용을 해석하고, 해석된 명령을 커널(kernel)에서 받아들여 실행할 수 있게끔 도와주는 명령어 처리기(command interpreter)이다. 커널은 하드웨어와 인터페이스하는 부분이다. 커널은 하드웨어와 사용자 프로그램의 중간에 위치하며, CPU, 메모리, 하드디스크 등의 하드웨어 자원을 제어하여 프로세스 스케쥴링, 기억장치 관리, 파일 관리, 시스템 호출 인터페이스, 멀티프로그래밍 지원, 파일 시스템 서비스, 입출력 서비스 등의 기능을 사용자에게 제공하는 운영체제의 핵심이다. shell은 커널에서 분리된 별도의 프로그램이다. 예를 들어, 사용자가 ls 명령을 입력하면 커널은 디스크로부터 파일의 이름을 읽어들인 다음 그 결과를 화면에 출력한다.
5.1.1 쉘(shell) 확인 및 변경 [root @edu00 /root]#echo $SHELL : shell 확인 /bin/bash [root @edu00 /root]#vi /etc/shells [root @edu00 /root]#chsh : shell 변경 Changing shell for 계정 Password: New shell[/bin/bash]:/bin/csh Shell changed [root @edu00 root]#echo $SHELL /bin/csh
5.1.1.1 Default PATH 사용하고자 하는 명령어들은 모두 PATH 변수에 들어 있는 디렉토리 안에 있어야 한다. 그 디렉토리에 들어 있지 않은 명령을 실행하기 위해서는 완전한 경로명을 적어주어야 한다. [root @edu00 /root]#echo $PATH
한라인에서 여러 명령어 사용하기 [root @edu00 linux]#ls ; cd public_html
여러 라인에 하나의 명령어 사용하기 [root @edu00 linux]#ls -l public_html \ >linuxnara
5.1.1.2 명령어 history 기능 [root @edu00 /root]#vi ~/.bash_history [root @edu00 /root]#history [root @edu00 /root]#history 10
5.1.1.3 명령(파일이릉) 완성 기능 [root @edu00 linux]#ls [Tab 키 2번] [root @edu00 linux]#ls /etc/pass [Tab 키 2번]
5.1.1.4 alias 기능 alias 별명이름=실행될 명령의 정의 [root @edu00 /root]#vi ~/.bashrc alias dir="ls -al | more" [root @edu00 /root]#source ~/.bashrc : 설정 적용
[root @edu00 linux]#alias lcd=”ls ; cd /home” : 쉘이 끝나면 설정도 사라진다. [root @edu00 linux]#alias lcd [root @edu00 linux]#lcd
5.1.2 인용(quoting) 규칙 5.1.2.1 metacharacter ~ 홈 디렉토리 ` 명령 대체(command substitution) # 주석(comment) $ Shell 변수 & 후면 작업(background job) * 문자열 wildcard () 부속 shell(subshell) \ escape 문자 | 파이프(pipe) [] 문자 집합 wildcard {} 명령 집합 ; shell 명령 분리자 < 입력 재지정 > 출력 재지정 / 경로명 디렉토리 분리자 ? 한 문자 wildcard ! 명령문 history
5.1.2.2 $ (dollar sign) shell 변수를 나타낼 때 사용하며, 변수에 특정한 값을 부여할 때는 =를 사용한다. [root @edu00 /root]#LANG=ko_KR [root @edu00 /root]#echo $LANG ko_KR [root @edu00 /root]#export LANG [root @edu00 /root]#date [root @edu00 /root]#LANG=euc_UN [root @edu00 /root]#echo $LANG euc_UN [root @edu00 /root]#export LANG [root @edu00 /root]##date
[root @edu00 /root]#echo $PATH
5.1.2.3 single quotes: ' ' 따옴표 안에 있는 모든 문자들의 특별한 의미를 제거한다. [root @edu00 /root]#echo '$PATH' $PATH
5.1.2.4 double quotes: " " 따옴표 안에 있는 문자들의 특정한 의미를 보호한다. [root @edu00 /root]#echo "$PATH"
5.1.2.5 backslash: \ backslash 다음에 오는 문자의 특별한 의미를 제거한다. [root @edu00 /root]#echo \$PATH $PATH
5.1.2.6 back quotes: ` ` 안에 있는 문자열을 명령어로 인식하여 대체 [root @edu00 root]#echo "Current Working Directory is `pwd`"
5.1.3 파일 이름 확장 특수 문자를 이용하여 한 번에 여러 개의 파일이나 경로명을 표시할 수 있다. 와일드 카드 문자를 사용하여 임의의 문자를 대체할 수 있다. ? 한 문자를 대체 * 임의의 길이의 문자를 대체 [chars] chars 문자 중의 하나로 대체 [!chars] chars에 없는 문자 중의 하나로 대체 [^chars] chars에 없는 문자 중의 하나로 대체
[ ]은 [ 과 ] 사이에 문자를 나열하여 "-중의 하나"로 표현, 범위를 지정할 때는 "-" [abc] [.,;] [-_] [*?] [a-z] [A-Z] [!0-9] [a-zA-Z]
5.1.4 환경 명령 set : 환경 변수와 사용자가 정의한 로컬 변수 등 모든 쉘 변수를 보여준다. env : 시스템의 환경 변수를 보여준다. export : 지역 변수를 환경 변수로 만든다. unset : 변수를 없앤다.
[root @edu00 root]#env
[root @edu00 root]#set
[root @edu00 root]#LANG=ko_KR [root @edu00 root]#export LANG or [root @edu00 root]#export LANG=ko_KR
5.1.5 명령어 히스토리(command history) 입력하여 실행했던 모든 명령들은 히스토리 리스트 버퍼에 저장이 된다. 명령행에서 입력해 사용한 명령들은 스택에 저장되어 다시 그 명령어를 사용할 때는 스택에서 꺼내어 사용할 수 있다. 히스토리 파일은 각 사용자의 홈 디렉토리에 .bash_history 라는 이름으로 존재하며, 쉘 실행 중에는 메모리에만 명령어 히스토리를 기억하고 있다가 쉘을 중단했을 때 .bash_history 파일에 저장된다. 명령행에서 history 명령을 실행하면, 히스토리 리스트에 있는 명령어들이 번호순으로 출력된다. HISTSIZE 변수에 히스토리 스택의 크기가 지정되어 있으며, HISTFILE에는 히스토리 파일의 위치가, HISTFILESIZE에는 히스토리 파일의 크기가 지정되어 있다. [root @edu00 root]#echo $HISTFILE /root/.bash_history [root @edu00 root]#echo $HISTSIZE 1000 [root @edu00 root]#HISTSIZE=1 [root @edu00 root]#echo $HISTSIZE 1 [root @edu00 root]#history [root @edu00 root]#HISTSIZE=100 [root @edu00 root]#echo $HISTSIZE 100 [root @edu00 root]#history
히스토리 명령문은 !를 이용하여 대체할 수 있다. !! !n !-n !string : 가장 최근에 string으로 시작하는 명령문을 실행한다. !?string? : 가장 최근에 실행했던 명령문 중 string을 포함하는 명령문을 실행한다. ^string1^string : 마지막 실행 명령문의 string1을 string2로 대체한 후 실행한다.
5.1.6 alias alias 별명이름=실행될 명령의 정의 alias를 현재 로그인되어 있는 상태뿐만 아니라 앞으로도 계속 사용하고 싶다면, ~/.bashrc 파일에 추가하여 사용할 수 있다. 설정 내용을 적용하여 사용하고자 할 경우#source ~/.bashrc
[root @edu00 /root]#alias : 현재 쉘에서 사용되고 있는 alias 목록 나열
[root @edu00 /root]#alias 별명 : 별명이 어떻게 정의되어 있는지 확인
[root @edu00 /root]#unalias : 현재 로그인되어 있는 상태에서만 alias 사용하지 않기 위해서 사용 계속 사용하지 않으려면 ~/.bashrc 파일에서 해당 설정 라인을 삭제 [root @edu00 /root]#unalias 별명
5.1.7 Redirection 초기값으로 쉘 프롬프트에서 입력하는 것은 표준 입력이라고 하여, stdin이라는 파일로 처리되며, 그 입력을 쉘에서 처리해서 그 결과를 터미널로 다시 보여준다면 그것은 표준 출력이라고 하여 stdout이라는 파일로 처리된다. [root @edu00 linux]#cat < /etc/passwd > /home/linuxpasswd [root @edu00 linux]#cat << END : END라는 문자열이 나올 때까지 계속해서 문자를 stdin으로 받게 된다.
>hi linux >hello!! END >END >^D
5.1.8 파이프라인 유닉스에서는 각각 다른 명령어들을 두개 이상 서로 연결해서 사용할 수 있다. 파이프는 현재 명령의 표준 출력을 다음 명령의 표준 입력으로 사용하는 것을 말한다. [root @edu00 linux]#who | wc –l [root @edu00 linux]#ps aux | grep httpd
5.1.9 로그인 /etc/passwd 파일의 패스워드 필드가 *등으로 lock되어 있는 계정도 쉘 부분에 정상적인 쉘이 들어있다면(/bin/false가 아닌 /bin/sh) 정상적인 쉘로 로그인된다. 사용자가 시스템에 로그인을 하게 되면 각각의 사용자에게는 시스템에 의해서 shell이 부여된다. 물론 로그인을 하더라도 shell이 부여되지 않는 경우도 있으나 그것은 해당 사용자에게 시스템 관리자가 shell을 부여하지 않겠다고 세팅을 함으로써 가능하다. shell이 부여된 사용자는 시스템내에서 shell상태에 놓여있다고 할 수 있으며, 이 사용자는 shell을 이용하여 프로그램들을 실행시킬 수 있다.
5.2 shell script
5.2.1 설정 명령 라인을 특정한 파일에 저장하고 실행하면 그 명령들이 차례대로 실행된다. [root @edu00 /root]#cd /home/linux [root @edu00 linux]#cat > ex1.sh mkdir nadream touch nadream/file_ls clear ^d
실행 [root @edu00 linux]#. ex1.sh or [root @edu00 linux]#source ex1.sh
결과 [root @edu00 linux]#ls nadream
5.2.2 문법과 예제 5.2.2.1 변수의 사용 변수(Variables)는 기억장소로 변수에는 정수, 문자열 등이 들어간다. [root @edu00 linux]#vi ex2.sh ### exam.sh ### 파일이름은 무엇이든 상관없다. my="Hi ther" my라는 변수에 "Hi there"라는 값을 넣는다. echo $my my변수 안에 들어있는 "Hi there"라는 값을 출력한다. echo "$my" my변수 안에 들어있는 "Hi there"라는 값을 출력한다. echo '$my' ' '안의 변수는 무시된다. $my 문자열을 출력한다. echo \$my \$는 \뒤의 특수 문자를 출력할 때 사용한다. echo Enter some text read my my의 값을 키보드로부터 입력 받는다. echo "$my" exit :wq
[root @edu00 linux]#. ex2.sh 실행이 끝나고 나면 logout될 것이다. exit 명령이 실행되었기 때문이다. 현재 실행 중인 bash process가 script를 해석하므로 exit 명령을 자신에게 적용시켜 logout된 것이다.
5.2.2.2 스크립트 실행하는 방법 이 예제는 logout되지 않는다.
[root @edu00 linux]#vi ex2.sh #!/bin/sh ### exam.sh ### 파일이름은 무엇이든 상관없다. my="Hi ther" my라는 변수에 "Hi there"라는 값을 넣는다. echo $my my변수 안에 들어있는 "Hi there"라는 값을 출력한다. echo "$my" my변수 안에 들어있는 "Hi there"라는 값을 출력한다. echo '$my' ''안의 변수는 무시된다. $my 문자열을 출력한다. echo \$my \$는 \뒤의 특수 문자를 출력할 때 사용한다. echo Enter some text read my my의 값을 키보드로부터 입력받는다. echo "$my" exit :wq
à #!/bin/sh magic number는 아래에 나오는 명령들을 해석할 shell을 명시해주는 것이다. 이것을 script file의 처음에 넣어 줌으로써 실행 파일로 만들 수 있다. '#!/bin/sh'의 의미는 아래에 나오는 명령들을 /bin/sh 프로그램이 해석할 것이라는 것이다. [root @edu00 linux]#chmod +x ex2.sh [root @edu00 linux]#./ex2.sh 현재 디렉토리는 PATH(환경변수)에 있지 않기 때문에 경로를 지정하여 실행한다. 새로운 bash process가 실행되어 script를 해석하므로 exit명령은 새로 실행된 bash에게 적용되어 그 process가 사라진 것이다.
5.2.2.3 if 와 test([]) 1] 문자열 비교 string1 = string2 string1과 string2가 같으면 참 string1 != string2 string1과 string2가 같으면 거짓 -n string 문자열이 있으면 참 -z string 문자열이 null이면 참
2] 산술 비교 a -eq b a와 b가 같으면 참 -ne 같지 않다. -gt 보다 크다. -ge 크거나 같다. -lt 보다 작다. -le 작거나 같다. ! expression 부정 3] 파일 조건 -d filepath filepath가 디렉토리이면 참 -e 존재 -f 정규 파일 -g set-gid -r 읽기 가능 -s 크기가 있으면 참 -u set-uid -w 쓰기 가능 -x 실행 가능
5.2.2.4 예제 [root @edu00 linux]#vi ex_if.sh #!/bin/sh ### ex_if.sh #### echo "Is it morning? Please answer yes or no." # echo 명령은 " "안에 있는 내용을 출력 read timeofday # timeofday라는 변수에 키보드 입력 if [ "$timeofday" = "yes" ] # []는 test 구문이므로 []안의 내용이 true인지 false인지 구별 # timeofday 변수값이 yes이면 true를 리턴하고 아니면 false를 리턴 then // 값이 true이면 then이하의 명령을 실행 echo "Good morning"
elif [ "$timeofday" = "no" ] # test 구문값이 false이면 다시 timeofday의 값이 no인지 test then // no이면 then 이하의 명령을 실행 echo "Good afternoon" else // no가 아니면 다음 명령을 실행 echo "Sorry, $timeofday not recognized. Enter yes or no." fi // if 구문을 마칠 때 fi 입력 exit :wq
5.2.2.5 for [root @edu00 linux] #vi for.sh #!/bin/sh ### for.sh ### for nadream in bar fud 43 # nadream은 in, bar, fud를 차례대로 받아서 do와 done사이의 명령을 실행 do echo $nadream # nadream변수를 출력한다. bar, fud, 43을 순서대로 출력 done for nadream in $(ls) # shell prompt 상태에서 ls 명령을 실행해서 출력되는 내용이 차례로 nadream에 들어# 가게 한다. do echo -n $nadream # -n은 행을 바꾸지 않고 계속해서 출력하게 한다. done exit :wq
[root @edu00 linux]#chmod 755 for.sh ; ./for.sh
5.2.2.6 while while 구문은 [ ] 안의 내용이 참일 때 계속해서 do와 done 사이의 명령을 실행한다. [root @edu00 linux]#vi while.sh #!/bin/sh echo "Enter password" read trythis while [ "$trythis" != "secret" ] # test가 참일 동안 do와 done사이의 명령을 실행 do echo "Sorry, try again" read trythis done exit :wq
[root @edu00 linux] #vi while2.sh #!/bin/sh nadream=1 while [ "$nadream" -le 20 ] # nadream값이 20보다 작거나 같다. do echo "Here we go again" nadream=$(($nadream+1)) # nadream에 1을 더한 값을 다시 nadream에 넣는다. done exit :wq
5.2.2.7 bash shell에서 login시 실행되는 script [root @edu00 linux]#cat ~/.bashrc ## .bashrc ## User specific aliases and functions alias rm='rm -i' alias cp='cp -i' alias mv='mv -i'
## Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi
[root @edu00 linux]#cat /etc/profile ## /etc/profile ## System wide environment and startup programs # Functions and aliases go in /etc/bashrc if ! echo $PATH | /bin/grep -q "/usr/X11R6/bin" ; then PATH="$PATH:/usr/X11R6/bin" fi ulimit -S -c 1000000 > /dev/null 2>&1 if [ `id -gn` = `id -un` -a `id -u` -gt 14 ]; then umask 002 else umask 022 fi
if [ -z "$INPUTRC" -a ! -f "$HOME/.inputrc" ]; then INPUTRC=/etc/inputrc fi
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC
for i in /etc/profile.d/*.sh ; do if [ -x $i ]; then . $i fi done
unset i
5.2.2.8 until while과 반대로 작동한다. 거짓일 경우 do와 done사이의 명령을 수행한다. [root @edu00 linux]#vi until.sh ### unitl.sh ### #!/bin/sh until who | grep "$1" > /dev/null # who | grep "$1" > /dev/null 명령이 실행될 때까지 do, done 사이의 명령을 실행한다. # 즉 조건이 참이면 실행을 멈춘다. do sleep 30 # 30초 동안 아무것도 하지 않는다. done echo "***** $1 has just logged in ****" # $1은 script를 실행할 때 인수로 쓰이는 것을 말한다. exit
5.2.2.9 case [root @edu00 linux]#vi case.sh #!/bin/sh echo "Is it morning? Please answer yes or no" read timeofday
case "$timeofday" in "yes" | "y" | "Yes" | "YES" ) # timeofday가 4개 중의 하나라면 아래 명령을 실행한다. echo "good morning" echo "Up bright and early this morning";; [Nn]* ) # 메타 문자가 사용 가능하다. # 앞에 N이나 n이 오고 뒤에는 아무런 문자가 와도 된다. echo "good afternoon";; * ) echo "Sorry, answer not recognized" # 위에 설정된 문자 외의 값을 갖는 경우에는 아래 명령을 실행한다. echo "Please answer yes or no" exit 1 ;; esac # case 문을 마칠 때 반대인 esac로 한다. exit
[root @edu00 linux]#chmod 755 case.sh ; ./case.sh
5.2.2.10 and statement1 && statement2 && statement3 ... 왼쪽부터 시작하여 그 결과값이 참이면 그 다음 명령이 수행된다. 하나의 구문이 거짓이 될 때까지 수행을 계속하며, 구문이 거짓을 반환한다면 더 이상 구문은 수행되지 않는다. [root @edu00 linux]#vi and.sh #!/bin/sh touch file_one rm -f file_two # 4개의 조건이 모두 만족하면 if in, 그렇지 않으면 in else # file_one이 있다면 echo 명령을 실행하고 file_two가 있다면 그 다음 echo 명령을 # 실행하게 된다. 만약 이 조건 중 하나라도 거짓이 나오면 거짓이 된다. if [ -f file_one ] && echo "hello" && [ -f file_two ] && echo "there" then echo "if in" else echo "in else" fi exit 0 :wq
5.2.2.11 or statement1 || statement2 || ... 왼쪽부터 시작하여 그 결과값이 거짓이면 오른편의 명령이 수행된다. 하나의 구문이 참이 될 때까지 수행을 계속한다. 만일 어떤 구문이 참을 반환하면 더 이상 수행하지 않는다. [root @edu00 linux] #vi or.sh #!/bin/sh rm -f file_one if [ -f file_one ] || echo "hello" || echo "there" # file_one이 있다면 다음의 echo 명령을 수행하지 않는다. # 없다면 echo "hello"를 수행하고 그 뒤의 echo "there"는 수행하지 않는다. # 3개 중 어느 하나가 참이면 참이 된다.
then echo "in if" else echo "in else" fi exit 0
5.2.2.12 함수 함수를 정의하는 것은 call 하는 것보다 먼저 나와야 한다. [root @edu00 linux]#vi func1.sh #!/bin/sh nadream() { # function() { 명령 ....} 이렇게 정의해서 쓴다. echo "Function nadream is excuting" } echo "script starting" nadream # 함수로 정의되어 있는 것을 불러다 쓴다. echo "script ended" exit 0
[root @edu00 linux] #vi func2.sh #!/bin/sh yes_or_no() { echo "parameters are \"$*\"" # $*은 $1부터 마지막 인수까지 전체를 나타낸다. # ./script nadream nadream2 nadream3라고 하면 $*의 값은 "nadream nadream1 # nadream2"가 된다. while true do echo -n "Enter yes or no" read x
case "$x" in y | yes ) return 0;; # 함수의 값은 0이 된다. n | no ) return 1;; * ) echo "Answer yes or no";; esac done }
echo "Original parameters are \"$*\"" # $*은 인수로 받은 것을 출력한다.
if yes_or_no "Is your name $1" # 이 파일을 실행시에 주었던 인수 중 첫번째 인수($1)를 포함한 "Is your name # $1"을 yes_or_no 함수의 인수로 넘겨준다. then echo "Hi $1" # 0을 받으면 실행 else echo "Never mind" # 1을 받으면 실행 fi exit 0
5.3 root shell 5.3.1 SetUID의 위험성 어떤 사람이든 suid가 설정된 파일을 실행하면 그 파일의 소유자의 계정(ID)으로 그 프로그램이 실행된다. [ cat ] 이 프로그램은 파일을 읽거나, 쓸수 있는 기능을 가지고 있다. 예를 들면, $cat /etc/passwd 라고 하면 /etc/passwd 파일을 읽는다.
만약 nadream이라는 사람이 만든 file이 있는데 permission이 일반 사용자들에게는 허가되지 않는다. -rw------- 1 nadream admin 45147 8월 19일 15:45 /tmp/passwd $ whoami guest
$ls -al /tmp/passwd -rw------- 1 nadream admin 45147 8월 19일 15:45 /tmp/passwd
$ls -al /bin/cat -r-xr-xr-x 1 bin bin 9388 Jul 16 1997 /bin/cat
$cat /tmp/passwd cat: cannot open /tmp/passwd /tmp/passwd 파일은 있지만 cat 으로 파일을 열수 없다. guest에게는 permission이 허가되지 않는다.
이번에는 /tmp/passwd 파일을 읽을 수 있다. $ whoami guest
$ls -al /tmp/passwd -rw------- 1 nadream admin 45147 8월 19일 15:45 /tmp/passwd
$ cat /tmp/passwd 해답은 바로 /bin/cat 라는 file의 permission을 보면 된다. cat의 소유자는 nadream이고 setuid 가 설정되어 있다. 즉, 현재의 guest사용자 계정이 cat이라는 프로그램을 실행하는 순간만큼은 nadream이라는 아이디로 실행한 것이다.
[ /bin/more ] more 라는 프로그램도 cat과 같이 파일을 읽을 수 있는 기능을 가지고 있다. 하지만 cat 명령과 다른 점은 한 페이지가 넘는 문서 파일일 경우 아무 키나 누르도록 하고 화면을 정지 시킨다. 도스의 dir /p 명령과 같이 p 옵션을 줘서 화면을 멈추게 하는 것이다. cat 대신 more 라는 파일에 setuid 를 주고 다시 한번 /tmp/passwd 파일을 보자. $ whoami guest
$ls -al /tmp/passwd -rw------- 1 nadream admin 45147 8월 19일 15:45 /tmp/passwd
cat 명령과 비슷하다. 다만 --More--(2%) 라는 것이 나와서 페이지 별로 내용을 볼 수 있을 뿐..
more 의 내부 명령 ! (느낌표) 명령은 그 뒤에 붙인 file을 실행하라는 명령 !cat /tmp/passwd라고 명령을 내리면 현재의 권한으로 cat /tmp/passwd 명령과 같다.
5.3.2 /bin/sh /bin/sh라는 것은 자주 여러분이 실행시키고, 무의식적으로 넘어가는 부분이다. /etc/passwd 파일에 해당 쉘이 지정되어 있다.
/bin/sh(쉘:SHELL) 파일의 쓰임은 흔히 사용하는 도스의 command.com 파일과 같다. "명령어 해석기"라 한다. unix 시스템에 로그인을 하게 되면 /etc/passwd 파일의 마지막에 붙어있는 /bin/sh가 실행되면서 prompt가 뜨게 된다. $ 혹은 # -> 쉘이 실행된 것을 의미한다. 쉘이 실행되면 그때부터 유닉스의 모든 명령을 내릴 수가 있다. /bin/sh파일에 손상이 가거나 삭제되면 로그인을 못하게 되는 결과를 낳게 된다.
** 그렇다면 이런 식의 행동은 어떤 결과를 부를까? more를 사용하는 과정에서 !/bin/sh라고 치게 되면 어떨까? 쉘을 실행했으니 $화면이 나올 것이다. 또한 현재 실행되는 suid는 유효할 것이다. 그렇다면 whoami를 이상태에서 치면? 내리는 명령마다 nadream으로 실행할 수 있을 것이다. setuid는 아직까지도 유효하기 때문이다. 아직 more 프로그램은 종료된게 아니라 more 의 ! 라는 내부 명령어 안에 있는 것이기 때문이다.
다음은 당신이 계정에 접속한후 more 를 실행해 !로 쉘로 빠진 경우를 보여준다. login -> /bin/sh -> more -> ! -> /bin/sh -> ls , cat, vi, telnet , ftp .. 등등
5.3.3 RootShell setuid 가 root 로 되어있는 쉘을 말한다. 실행할 파일이 /bin/sh 이고 그 소유자가 root인 경우 : -r-sr-xr-x 3 root 88620 Jul 16 1997 /bin/sh