제6장 쉘
6.1 쉘 소개
쉘(Shell)이란 무엇인가? 쉘의 역할 쉘은 사용자와 운영체제 사이에 창구 역할을 하는 소프트웨어 명령어 처리기(command processor) 사용자로부터 명령어를 입력받아 이를 처리한다
쉘의 종류 유닉스/리눅스에서 사용 가능한 쉘의 종류 쉘의 종류 쉘 실행 파일 본 쉘 /bin/sh 콘 쉘 /bin/ksh C 쉘 /bin/csh Bash /bin/bash tcsh /bin/tcsh
쉘의 종류 본 쉘(Bourne shell) 콘 쉘(Korn shell) Bash(Bourne again shell) 벨연구소의 스티븐 본(Stephen Bourne)에 의해 개발됨 유닉스에서 기본 쉘로 사용됨 콘 쉘(Korn shell) 1980년대에는 역시 벨연구소에서 본 쉘을 확장해서 만듬. Bash(Bourne again shell) GNU에서 본 쉘을 확장하여 개발한 쉘 리눅스 및 맥 OS X에서 기본 쉘로 사용되면서 널리 보급됨 Bash 명령어의 구문은 본 쉘 명령어 구문을 확장함 C 쉘(C shell) 버클리대학의 빌 조이(Bill Joy) 쉘의 핵심 기능 위에 C 언어의 특징을 많이 포함함 BSD 계열의 유닉스에서 많이 사용됨 최근에 이를 개선한 tcsh이 개발됨어 되어 사용됨
로그인 쉘(login shell) 로그인 하면 자동으로 실행되는 쉘 보통 시스템관리자가 계정을 만들 때 로그인 쉘 지정 $ cat /etc/passwd | grep mysung ... mysung:x:503:503:mysung:/home/mysung:/bin/bash 로그인 쉘 변경(리눅스) $ cat /etc/passwd | grep 자기아이디 $ chsh Changing shell for mysung. 암호: New shell [/bin/bash]: /bin/csh Shell changed. 또는 다시 로그인하여 % ps PID TTY TIME CMD 23750 pts/2 00:00:00 csh 23780 pts/2 00:00:00 ps
6.2 쉘의 기본 기능
쉘의 기본 기능 명령어 처리 시작 파일 스크립트 사용자가 입력한 명령을 해석하고 적절한 프로그램을 실행 로그인할 때 실행되어 사용자별로 맞춤형 사용 환경 설정 스크립트 쉘 자체 내의 프로그래밍 기능 (7장)
쉘의 실행 절차
시작 파일(start-up file) 환경 변수 확인 쉘마다 시작될 때 자동으로 실행되는 고유의 시작 파일 쉘마다 시작될 때 자동으로 실행되는 고유의 시작 파일 주로 사용자 환경을 설정하는 역할을 하며 환경설정을 위해서 환경변수에 적절한 값을 설정한다 $ 환경변수명=문자열 $ TERM=xterm $ echo $TERM xterm export 명령어: 지역변수를 환경변수화 $ name=나가수 $ sh $ echo $name $ name=나가수; export name 환경 변수 확인 $ env REMOTEHOST=117.16.244.61 XDG_SESSION_ID=5459 HOSTNAME=localhost.localdomai n SHELL=/bin/bash TERM=ansi HISTSIZE=1000 QTDIR=/usr/lib/qt-3.3 QTINC=/usr/lib/qt-3.3/include USER=mysung ...
시작 파일(start-up file) 본 쉘 bash C 쉘 /etc/profile ~/.profile /etc/bashrc ~/.bash_profile ~/.bashrc C 쉘 /etc/.login ~/.login ~/.cshrc
시작 파일 예 .bash_profile 시작 파일 바로 적용 PATH=$PATH:$HOME/bin:. export PATH PS1="[\u@\h \w]\$ " 시작 파일 바로 적용 $ . .bash_profile
.bash_profile 쉘 환경변수 프롬프트 설정 $HOME, $PATH, $SHELL, $TERM, $LOGNAME, $PS1, $PS2, $IFS 프롬프트 설정 $ PS1=“$PWD \$” $ PS1=“\$PWD \$ ” $PWD의 실행이 shell의 해석으로부터 보호되어 매 프롬프트 생성 때마다 실행 $ PS1=“\u@\h \w \$ ” $ vi .bash_profile (쉘 환경변수 PATH 및 자기 취향의 PS1 설정) vi 편집 중 문법 체크 옵션 관련 색상 없애려면 :syntax off PATH=$PATH:$HOME/bin:. PS1=“\u@\h \w \$ ” $ . .bash_profile로 실행시켜 적용 IFS: Input Field Separators PS1: Prompt String 1 PS2: Prompt String 2
.bash_profile 프롬프트에 사용할 수 있는 제어문자 \t 현재 시간(시:분:초 형식) \d 오늘 날짜, 요일(요일 월 일 형식) \n new line \s 현재 셸 이름, $0의 값 \w 현재 작업 디렉토리의 이름 (전체경로까지) \W 현재 작업 디렉토리의 이름 (현재 위치만) \u 사용자 이름 \h 호스트 이름 \# 셸이 기동한 후로부터의 명령의 번호 \! 실행하는 명령의 history 번호 \$ 프롬프트 모양 uid가 0, root이면 #, 그렇지 않으면 $ \nnn ASCII 코드 nnn에 해당하는 문자 \\ 백슬래시 \[ 제어문자라 쓸 수 없는 문자를 사용하기 위해서는 [로 시작 \] 제어문자의 끝
6.3 쉘 명령어 처리
쉘 명령어 종류 내장 명령어 (유틸리티와의 차이: shell에 내장, search path에서 찾기 전에 실행) 쉘 내에 내장되어 있는 명령어 <Linux> $ man builtins <Unix> $ man shell_builtins $ man builtins bash, :, ., [, alias, bg, bind, break, builtin, caller, cd, command, compgen, complete, compopt, continue, declare, dirs, disown, echo, enable, eval, exec, exit, export, false, fc, fg, getopts, hash, help, history, jobs, kill, let, local, logout, mapfile, popd, printf, pushd, pwd, read, readonly, return, set, shift, shopt, source, suspend, test, times, trap, true, type, typeset, ulimit, umask, unalias, unset, wait $ echo {string}* $ echo –n {string}* $ echo –e “string” (예) $ echo –e "\0110\0151” 유틸리티 프로그램 (=내장되어 있지 않은 명령어들, search path에서 찾아서 실행) 명령어를 위한 실행 파일이 별도로 존재하는 명령어 $ ls /bin/ls 환경변수 PATH PATH=/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/mysung/bin:.
내장 명령어 <Linux> $ man builtins <Unix> $ man shell_builtins 로 내장명령어 확인 정보를 표시 : echo 모든 명령어 인자(arg)들을 표준 출력(화면)에 표시해줌 Borne shell, Bash shell에서 $ echo {string}* $ echo –n {string}* 출력에 newline을 생성(default)하지 않도록 해줌 $ echo –e “string” 제어문자 표시: 큰 따옴표 안에 표기 \b backspace \c print line without new-line (Fedora Core 15에서는 적용 안됨) \f form-feed \n new-line \r carriage return \t tab \v vertical tab \\ backslash \0n where n is the 8-bit character whose ASCII code is the 1-, 2- or 3-digit octal number representing that character (예) $ echo –e “\0101” $ echo –e “\0141” $ echo –e “\0117\n\0113”
ASCII Code Unix/Linux * 1 2 3 4 5 6 7 8 9 A B C D E F NUL SOH STX ETX 1 2 3 4 5 6 7 8 9 A B C D E F NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US ! " # $ % & ' ( ) + , - . / : ; < = > ? @ G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ Unix/Linux
Unix/Linux 10진수 16진수 8진수 2진수 ASCII 0×00 000 0000000 NULL 64 0×40 100 0×00 000 0000000 NULL 64 0×40 100 1000000 @ 1 0×01 001 0000001 SOH 65 0×41 101 1000001 A 2 0×02 002 0000010 STX 66 0×42 102 1000010 B 3 0×03 003 0000011 ETX 67 0×43 103 1000011 C 4 0×04 004 0000100 EOT 68 0×44 104 1000100 D 5 0×05 005 0000101 ENQ 69 0×45 105 1000101 E 6 0×06 006 0000110 ACK 70 0×46 106 1000110 F 7 0×07 007 0000111 BEL 71 0×47 107 1000111 G 8 0×08 010 0001000 BS 72 0×48 110 1001000 H 9 0×09 011 0001001 HT 73 0×49 111 1001001 I 10 0×0A 012 0001010 LF 74 0×4A 112 1001010 J 11 0×0B 013 0001011 VT 75 0×4B 113 1001011 K 12 0×0C 014 0001100 FF 76 0×4C 114 1001100 L 13 0×0D 015 0001101 CR 77 0×4D 115 1001101 M 14 0×0E 016 0001110 SO 78 0×4E 116 1001110 N 15 0×0F 017 0001111 SI 79 0×4F 117 1001111 O 16 0×10 020 0010000 DLE 80 0×50 120 1010000 P 17 0×11 021 0010001 DC1 81 0×51 121 1010001 Q 18 0×12 022 0010010 SC2 82 0×52 122 1010010 R 19 0×13 023 0010011 SC3 83 0×53 123 1010011 S 20 0×14 024 0010100 SC4 84 0×54 124 1010100 T 21 0×15 025 0010101 NAK 85 0×55 125 1010101 U 22 0×16 026 0010110 SYN 86 0×56 126 1010110 V 23 0×17 027 0010111 ETB 87 0×57 127 1010111 W 24 0×18 030 0011000 CAN 88 0×58 130 1011000 X 25 0×19 031 0011001 EM 89 0×59 131 1011001 Y 26 0×1A 032 0011010 SUB 90 0×5A 132 1011010 Z 27 0×1B 033 0011011 ESC 91 0×5B 133 1011011 [ 28 0×1C 034 0011100 FS 92 0×5C 134 1011100 \ 29 0×1D 035 0011101 GS 93 0×5D 135 1011101 ] 30 0×1E 036 0011110 RS 94 0×5E 136 1011110 ^ 31 0×1F 037 0011111 US 95 0×5F 137 1011111 _ 32 0×20 040 0100000 SP 96 0×60 140 1100000 . 33 0×21 041 0100001 ! 97 0×61 141 1100001 a 34 0×22 042 0100010 " 98 0×62 142 1100010 b 35 0×23 043 0100011 # 99 0×63 143 1100011 c 36 0×24 044 0100100 $ 0×64 144 1100100 d 37 0×25 045 0100101 % 0×65 145 1100101 e 38 0×26 046 0100110 & 0×66 146 1100110 f 39 0×27 047 0100111 ' 0×67 147 1100111 g 40 0×28 050 0101000 ( 0×68 150 1101000 h 41 0×29 051 0101001 ) 0×69 151 1101001 i 42 0×2A 052 0101010 * 0×6A 152 1101010 j 43 0×2B 053 0101011 + 0×6B 153 1101011 k 44 0×2C 054 0101100 108 0×6C 154 1101100 l 45 0×2D 055 0101101 - 109 0×6D 155 1101101 m 46 0×2E 056 0101110 0×6E 156 1101110 n 47 0×2F 057 0101111 / 0×6F 157 1101111 o 48 0×30 060 0110000 0×70 160 1110000 p 49 0×31 061 0110001 0×71 161 1110001 q 50 0×32 062 0110010 0×72 162 1110010 r 51 0×33 063 0110011 0×73 163 1110011 s 52 0×34 064 0110100 0×74 164 1110100 t 53 0×35 065 0110101 0×75 165 1110101 u 54 0×36 066 0110110 118 0×76 166 1110110 v 55 0×37 067 0110111 119 0×77 167 1110111 w 56 0×38 070 0111000 0×78 170 1111000 x 57 0×39 071 0111001 0×79 171 1111001 y 58 0×3A 072 0111010 : 0×7A 172 1111010 z 59 0×3B 073 0111011 ; 0×7B 173 1111011 { 60 0×3C 074 0111100 < 0×7C 174 1111100 | 61 0×3D 075 0111101 = 0×7D 175 1111101 } 62 0×3E 076 0111110 > 0×7E 176 1111110 ~ 63 0×3F 077 0111111 ? 0×7F 177 1111111 DEL Unix/Linux
입출력 재지정 및 파이프 출력 재지정 출력 추가 입력 재지정 문서 내 입력 파이프 $ 명령어 > 파일 $ 명령어 >> 파일 입력 재지정 $ 명령어 < 파일 문서 내 입력 $ 명령어 << 단어 (Here Document) ... 단어 파이프 $ 명령어1 | 명령어2
복합 명령어 명령어 열(command sequence) 명령어 그룹(command group) $ 명령어1; … ; 명령어n $ date; who; pwd 명령어 그룹(command group) $ (명령어1; … ; 명령어n) $ date; who; pwd > out1 $ (date; who; pwd) > out2
조건 명령열(conditional command sequence) $ vi hello.c #include <stdio.h> main() { printf ("hello world!\n"); } $ 명령어1 && 명령어2 $ gcc hello.c && a.out $ 명령어1 || 명령어2 (hello.c 파일에 오류 만들고) $ gcc hello.c || echo 컴파일 실패
파일 이름 대치 대표문자를 이용한 파일 이름 대치 대표문자 대표문자를 이용하여 한 번에 여러 파일들을 나타냄 명령어 실행 전에 대표문자가 나타내는 파일 이름들로 먼저 대 치하고 실행 $ cat *.c $ cat a.c b.c c.c 대표문자 * 빈 스트링을 포함하여 임의의 스트링를 나타냄 ? 임의의 한 문자를 나타냄 [..] 대괄호 사이의 문자 중 하나를 나타내며 부분범위 사용 가능 $ ls *.c $ ls [ac]*
명령어 대치(command substitution) 명령어를 실행할 때 다른 명령어의 실행 결과를 이용 역따옴표(`)로 에워싼 다른 명령어 부분은 그 명령어의 실행 결 과로 대치된 후에 실행 $ echo 현재 시간은 `date` $ echo 현재 디렉터리 내의 파일의 개수 : `ls | wc -w` 현재 디렉터리 내의 파일의 개수 : 32
따옴표 사용 따옴표를 이용하여 대치 기능을 제한 $ echo 3 * 4 = 12 3 cat.csh count.csh grade.csh invite.csh menu.csh test.sh = 12 $ echo "3 * 4 = 12" 3 * 4 = 12 $ echo '3 * 4 = 12' $ name=나가수 $ echo "내 이름은 $name 현재 시간은 `date`" 내 이름은 나가수 현재 시간은 2013. 10. 21. (월) 11:47:18 KST $ echo '내 이름은 $name 현재 시간은 `date`' 내 이름은 $name 현재 시간은 `date`
따옴표 사용 정리 작은따옴표(')는 파일이름 대치, 변수 대치, 명령어 대치를 모 두 제한한다 큰따옴표(")는 파일이름 대치만 제한한다 따옴표가 중첩되면 밖에 따옴표가 효력을 갖는다
6.4 쉘 스크립트
쉘 스크립트 쉘 스크립트는? 쉘 스크립트 종류 명령어 및 유틸리티들을 적절히 사용하여 작성한 프로그램 1. 첫 번째 줄에 사용할 쉘을 #!경로명 형태로 지정 #!/bin/bash #!/bin/sh #!/bin/ksh #!/bin/csh 2. 단지 첫 번째 줄이 #으로 시작되면 C 쉘 스크립트로 간주 3. 그 외는 본 쉘 스크립트로 간주한다.
쉘 스크립트 작성 및 실행 에디터를 사용하여 스크립트 파일을 작성한다 chmod를 이용하여 실행 모드로 변경한다 $ vi state.bash #!/bin/bash echo –n 현재 시간: date echo 현재 사용자: who echo 시스템 현재 상황: uptime chmod를 이용하여 실행 모드로 변경한다 $ chmod +x state.bash 스크립트 이름을 타이핑하여 실행한 $ ./state.bash
6.5 작업 제어
프로세스 상태: ps ps [-옵션] 명령어 $ ps aux (BSD 유닉스) $ ps -ef (시스템 V) 현재 존재하는 프로세스들의 실행 상태를 요약해서 출력 $ ps PID TTY TIME CMD 25435 pts/3 00:00:00 csh 25461 pts/3 00:00:00 ps $ ps aux (BSD 유닉스) a: 모든 사용자의 프로세스를 출력 u: 프로세스에 대한 좀 더 자세한 정보를 출력 x: 더 이상 제어 터미널을 갖지 않은 프로세스들도 함께 출력 $ ps -ef (시스템 V) - e: 모든 사용자 프로세스 정보를 출력 - f: 프로세스에 대한 좀 더 자세한 정보를 출력 (cf.) $ pstree -p [ mysung ] (cf.) $ top (display Linux tasks)
kill kill 명령어 현재 실행중인 프로세스를 강제로 종료 디폴트는 TERM(-15) 신호는 signal()로 가로챌 수 있음 -KILL(-9)는 절대 가로챌 수 없으므로 확실하게 종료 $ kill [-시그널] 프로세스번호 $ kill -l $ (echo 시작; sleep 5; echo 끝) & 1234 $ kill 1234 $ kill -9 1234 $ kill -KILL 1234
sleep & wait sleep 명령어 wait 명령어 지정된 시간만큼 실행을 중지한다. $ sleep 초 $ (echo 시작; sleep 5; echo 끝) wait 명령어 해당 프로세스 번호를 갖는 자식 프로세스 가 종료될 때까지 기다린다 프로세스 번호를 지정하지 않으면 모든 자 식 프로세스를 기다린다 $ wait [프로세스번호] $ (sleep 50; echo done 1) & 1234 $ echo done 2; wait 1234; echo done 3 done 2 done 1 [1]+ Done ( sleep 100; echo done 1 ) done 3 다시 한번 $ (sleep 50; echo 1번 끝) & $ (sleep 50; echo 2번 끝) & $ echo done 3; wait; echo done 4 done 3 done 1 done 2 [1]- Done ( sleep 50; echo done 1 ) [2]+ Done ( sleep 50; echo done 2 ) done 4
기타 명령어 nohup (대부분 디폴트) $ nice $ renice $ id $ uname $ which echo 로그아웃 후에도 프로세스를 계속 실행 계속되기를 원하지 않으면 종료 후 logout $ nohup 명령어 [인수] & 명령어의 결과는 시스템 내의 nohup.out 파일에 기록 (예) $ nohup sleep 10000 & 디폴트임을 아래와 같이 확인 $ sleep 10000 & $ logout login $ ps aux | grep mysung $ nice 프로세스의 우선순위를 조정 $ ps -l $ sleep 1000 & $ nice -n +5 sleep 1000 & $ renice 실행 중인 프로세스의 우선순위를 조정 $ id 사용자 자신의 사용자 ID와 그룹 ID를 출력 $ uname 시스템 정보를 출력 (-a 모든 정보를 출력) $ which echo 쉘 명령어의 전체경로를 출력
6.6 내장 명령어
shift shit 명령어 shift.sh $ shift.sh a b c 명령줄 인수를 하나씩 왼쪽으로 이동한다. #!/bin/sh echo first argument is $1, all args are $* shift $ shift.sh a b c first argument is a, all args are a b c first argument is b, all args are b c
eval, exit, exec, umask eval exit exec umask $ echo x=5 $ echo $x $ eval `echo x=5` 5 exit 쉘을 종료하고 종료값(exit code)을 부모 프로세스에 전달한다 $ /bin/sh $ exit [종료값] $ echo $? exec exec는 현재 쉘을 명령어로 대치하고 명령어를 실행한다 $ exec date umask 파일이 생성될 때 허가권 설정을 제한하는 umask 값을 보여주거나 인수로 명시된 8진수로 설정한다 $ umask 0022 $ echo xx > xx ; ls –l xx $ umask 0066 $ echo yy > yy ; ls –l yy
핵심 개념 쉘은 사용자와 운영체제 사이에 창구 역할을 하는 소프트웨어로 사용자로부터 명령어를 입력받아 이를 처리하는 명령어 처리기 역 할을 한다 입력 재지정은 명령어의 표준입력을 키보드 대신에 파일에서 받게 한다. 출력 재지정은 명령어의 표준출력을 모니터 대신에 파일에 하게 한다 유닉스 명령어 및 유틸리티들을 적절히 사용하여 프로그램을 작성 할 수 있는데 이러한 프로그램을 쉘 스크립트라고 한다. 쉘에서 사용할 수 있는 명령어는 쉘 내에 내장되어 있는 내장 명 령어와 명령어를 위한 실행 파일이 별도로 존재하는 유틸리티 프 로그램이다
echo.c 코딩 & 컴파일 & 실행 $ gcc echo.c –o echo $ ./echo hello world! #include <stdio.h> main(int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) printf("%s%s", argv[i], (i < argc-1) ? " " : ""); printf("\n"); return 0; } echo.c 컴파일 & 실행 $ gcc echo.c –o echo $ ./echo hello world! [실습] 명령라인에서 $ ./myecho hello world! 실행하면 아래와 같이 출력되는 myecho.c 코딩 argc=3 argv[0]=“myecho” argv[1]=“hello” argv[2]=“world!” hello world!
(C언어 보충) Command-line Arguments $ ./myecho hello world! Output hello, world! argc 와 argv[] argc=3 argv[0]=“myecho” argv[1]=“hello” argv[2]=“world!” argv[3]=‘\0’ Source code $ cat myecho.c #include <stdio.h> main(int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) printf(“%s%s”, argv[i], (i < argc-1) ? “ ” : “”); printf(“\n”); return 0; } argv: myecho\0 hello\0 world!\0