UNIX 및실습 13 장보충 bash(1) 1
Bash bash(bourne Again Shell) 다양한내장명령과히스토리, 별명, 파일, 명령완성, 명령줄편집등지원 원래있던 Bourne Shell 에 GNU 프로젝트를통해추가된다양한기능들이많음 버전확인 [kgu@lily ~]$ bash --version GNU bash, version 4.2.37(1)-release (x86_64-redhat-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. 2
초기화파일 /etc/profile ~/.bash_profile 환경 없으면 ~/.bash_login 그마저도없으면 ~/.profile 3개중하나만처리.bashrc Bash 쉘에만적용되는특별한설정사항들 /etc/bashrc 시스템전체에서사용되는함수와별명들 3
변수확장변경자 (modifier) 서식지정자 ${variable:-word} 값 변수에 null 이아닌값이지정되어있으면변수값사용, 그렇지않으면 word 로잠시치환 ${variable:=word} 변수에 null 이아닌값이지정되어있으면변수값사용, 그렇지않으면 word 로설정 ( 영구치환 ) ${variable:+word} ${variable:?word} 변수에 null 이아닌값이지정되어있으면변수값을 word 로잠시치환, 그렇지않으면아무것도치환하지않는다. 변수에 null 이아닌값이지정되어있으면변수값사용, 그렇지않으면 word 를출력하고쉘종료. word 를생략하면 parameter null or not set 메시지출력 4
부분문자열에대한변수전개 표현식 기능 ${variable:offset} offset 에서시작하여변수 variable 의부분문자열추출. ${variable:offset:length} offset 에서시작하여 length 만큼변수 variable 의부분문자열추출. ${variable%pattern} Variable 값의후반부에서패턴과일치하는가장작은부분을찾아제거 ${variable%%pattern} Variable 값의후반부에서패턴과일치하는가장큰부분을찾아제거 ${variable#pattern} ${#variable} Variable 값의전반부에서패턴과일치하는가장작은부분을찾아제거 변수의문자수로치환. * 나 @ 를사용하면위치매개변수의개수를길이로사용 5
위치매개변수 위치매개변수의미 $0 현재쉘스크립트이름 $1 - $9 1번부터 9번까지위치매개변수 ${10} 10번위치매개변수 $# 위치매개변수총개수 $* 모든위치매개변수 $@ 큰따옴표를사용하였을때를제외하고는 $* 와동일 $* $1 $2 $3 로평가 $@ $1 $2 $3 으로평가 6
기타특수변수 특수변수 의미 $ 쉘의 PID - 쉘의현재설정된옵션? 최근에실행시킨명령의종료상태! 백그라운드에서실행시킨최근프로그램의 PID 7
인용부호의사용 (1) 메타문자의미 ; 명령구분자 & 백그라운드실행 ( ) 명령집합 : 새로운쉘에서실행 { } 명령집합 : 현재쉘에서실행 파이프 인용부호를필요로하는메타문자 메타문자의미 < 입력리다이렉션 > 출력리다이렉션 Newline 명령입력종료 Space/TAB 단어구분자 $ 변수치환문자 * [ ]? 파일명전개를위한쉘메타문자 8
인용부호사용 (2) 역슬래시 (\) 어떤문자가쉘에의해해석되지않도록보호 작은따옴표 ( ) 쌍으로사용 모든메타문자의해석을막는다 큰따옴표 ( ) 쌍으로사용 변수나명령치환은허용하고나머지특수메타문자들에대해서는쉘이해석하지않도록보호 9
Shell Built-in Commands (1) 명령 기능 : do-nothing; 0 반환. file 명령을 File 에서읽어수행 break [n] 반복문참조. 현재프로세스에서프로그램수행 (source 와동일 ) alias bg bind break 현재존재하는명령들에대한별명들을보여주거나설정 작업을백그라운드화 현재설정된키와기능바인딩을보여주거나, readline 이나매크로에서사용할수있도록키들을바인딩 가장안에있는루프에서탈출 built-in [ sh-built-in [ args ] ] 쉘빌트인을수행 (args 들을넘겨주고 0 반환 ) built-in 과 sh-built-in 이동일한이름일경우유용 cd [arg] 디렉토리변경 command command [ arg ] continue [ n ] declare [ var ] 함수와명령이동일한이름을가지더라도명령을수행 반복문참조 모든변수들을보여주거나변수선언 10
Shell Built-in Commands (2) 명령 dirs disown echo [ args ] enable eval [ args ] exec command exit [ n ] export [ var ] fc fg getopts hash help [ command ] history 기능 pushd로인해현재기억된디렉토리리스트를보여줌작업테이블에서실행중인작업제거 args를보이고줄을바꿈쉘빌트인명령을가용또는불용하게함 args를쉘의입력으로읽어실행현재쉘에서명령수행종료상태를 n으로반환하고종료자식쉘에게 var 상속히스트리목록을편집하기위한명령 (fix command) 백그라운드작업을포그라운드로가져옴명령줄에서지정한옵션을추출하기위해스크립트에서사용명령의빠른수행을위해내부해시테이블제어내장명령에대한도움말제공히스토리목록을행번호와같이출력 11
Shell Built-in Commands (3) 명령 jobs kill [ -signal process ] let local logout popd pushd pwd read [ var ] 기능 백그라운드작업목록을보여줌지정된 PID 번호나작업번호에시그널을보냄산술식을평가하거나산술계산결과를변수에저장하기위해사용변수의통용범위를함수내로제한하기위해사용로그린쉘종료디렉토리스택의항목을제거디렉토리스택에항목추가현재작업디렉토리를보여줌표준입력에서읽은내용을변수 var에저장 readonly [ var ] 변수 var 를읽기전용으로만듬 (var 은재설정이안됨 ) return [ n ] set shift [ n ] stop pid 종료상태를 n으로반환하고함수로부터복귀옵션과위치매개변수설정위치매개변수를지정한 n회만큼왼쪽으로이동지정된 PID 프로세스를중지 (halt) 12
Shell Built-in Commands (4) 명령 suspend test times trap [ arg ] [ n ] type [ command ] typeset ulimit umask [ octal_digits ] unalias unset [ name ] wait [ pid#n ] 기능 현재쉘의수행을일시중지 파일유형이나조건식을평가 현재쉘에서수행된프로세스들의수행시간에대한정보를출력 쉘은시그널 n 에대해 arg 를수행 명령의유형을출력 변수의설정이나속성을지정, declare 와동일 프로세스가사용할수있는자원의최대한계를설정 파일생성시에사용할권한을설정 별명의설정을해제 변수나함수의설정을해제 백스라운드에서수행되는지정한 PID 의프로세스가종료할때까지스크립트를일시중지 13
쉘스크립트작성절차 첫번째행에는스크립트를수행할때사용할쉘이름 #!/bin/bash 주석 #! 는매직넘버 ( 항상첫줄에나와야함 ) # 기호가앞서나오는줄 실행문과배쉬쉘구조 유닉스명령, 본쉘명령, 프로그램구조, 주석등으로구성 실행권한부여 반드시실행권한을부여해야만실행가능 14
예제쉘스크립트 1 2 [kgu@lily ch13]$ cat greeting.bash #!/bin/bash # This is the first Bash shell program of the day. # Scriptname: greetings # Written by: Barbara Bashful echo "Hello $LOGNAME, it's nice talking to you." echo "Your present working directory is `pwd`." echo "You are working on a machine called `uname -n`." echo "Here is a list of your files." ls # List files in the present working directory echo "Bye for now $LOGNAME. The time is `date +%T`!" [kgu@lily ch13]$ chmod +x greeting.bash [kgu@lily ch13]$./greeting.bash Hello kgu, it's nice talking to you. Your present working directory is /home/kgu/2013u1/ch13. You are working on a machine called lily.mmu.ac.kr. Here is a list of your files. greeting.bash Bye for now kgu. The time is 17:37:30! 15
read 명령 사용자입력읽기 (1) 형식 read answer read first last read read a arrayname read -e read p prompt read r line 의미 표준입력에서한줄읽어서변수 answer 에저장 표준입력에서한줄읽어서첫단어는 first 에, 나머지는 last 에저장 입력을 REPLY 에저장 입력을받은목록을 arrayname 배열에저장 입력줄에서명령줄편집사용입력줄을 vi 키를이용하여편집 문자열 prompt 를출력하고입력을기다린다. 입력은 REPLY 변수에저장 입력에역슬래시를쓸수있게허용 16
사용자입력읽기 (2) 3 [kgu@lily ch13]$ cat nosy.bash #!/bin/bash # Scriptname: nosy echo -e "Are you happy? \c" read answer echo "$answer is the right response." echo -e "What is your full name? \c" read first middle last echo "Hello $first" echo -n "Where do you work? " read echo I guess $REPLY keeps you busy! read -p "Enter your job title: " echo "I thought you might be an $REPLY." 4 [kgu@lily ch13]$ chmod +x nosy.bash [kgu@lily ch13]$./nosy.bash Are you happy? y y is the right response. What is your full name? kgu Hello kgu Where do you work? MMU I guess MMU keeps you busy! Enter your job title: Prof. I thought you might be an Prof.. Who are your best friends? kki kjw kjh Say hi to kjh. echo -n "Who are your best friends? " read -a friends echo "Say hi to ${friends[2]}." 17
사용자입력읽기 (3) 5 [root@lily ch13]# cat printer_check.bash #!/bin/bash # Scriptname: printer_check # Script to clear a hung-up printer if [ $LOGNAME!= root ] then echo "Must have root privileges to run this program" exit 1 fi cat << EOF Warning: All jobs in the printer queue will be removed. Please turn off the printer now. Press return when you are ready to continue. Otherwise press Control C. EOF read JUNK # Wait until the user turns off the printer echo /etc/rc.d/init.d/lpd stop # Stop the printer echo -e "\nplease turn the printer on now." echo "Press Enter to continue" read JUNK # Stall until the user turns the printer # back on echo # A blank line is printed /etc/rc.d/init.d/lpd start # Start the printer 18
declare 명령 6 산술연산 (1) declare i 로정수타입변수선언 [kgu@lily ch13]$ declare -i number [kgu@lily ch13]$ number=hello [kgu@lily ch13]$ echo $number 0 7 [kgu@lily ch13]$ number=5 + 5 bash: +: command not found... [kgu@lily ch13]$ number=5+5 [kgu@lily ch13]$ echo $number 10 [kgu@lily ch13]$ number=6.5 -bash: 6.5: syntax error: invalid arithmetic operator (error token is ".5") 19
산술연산 (2) 정수타입변수출력 8 9 [kgu@lily ch13]$ declare -i declare -ir BASHPID declare -ir EUID="1000" declare -i HISTCMD declare -i LINENO declare -i MAILCHECK="60" declare -i OPTIND="1" declare -ir PPID="6929" declare -i RANDOM declare -ir UID="1000" declare -i num="0" declare -i number="10" 다른수체계사용 [kgu@lily ch13]$ declare -i x=017 [kgu@lily ch13]$ echo $x 15 [kgu@lily ch13]$ x=2#101 [kgu@lily ch13]$ echo $x 5 [kgu@lily ch13]$ x=8#17 [kgu@lily ch13]$ echo $x 15 2 진수 101 8 진수 17 20
산술연산 (3) 10 let 명령 [kgu@lily ch13]$ i=5 [kgu@lily ch13]$ let i=i+1 [kgu@lily ch13]$ echo $i 6 [kgu@lily ch13]$ let "i = i + 2" [kgu@lily ch13]$ echo $i 8 [kgu@lily ch13]$ let "i+=1" [kgu@lily ch13]$ echo $i 9 [kgu@lily ch13]$ i=3 [kgu@lily ch13]$ (i+=4) [kgu@lily ch13]$ echo $i 3 [kgu@lily ch13]$ ((i+=4)) [kgu@lily ch13]$ echo $i 7 11 부동소숫점연산 bash 는정수타입연산만지원 bc, awk, nawk 등을이용하여복잡한계산수행 [kgu@lily ch13]$ n='echo "scale=3; 13/2" bc' [kgu@lily ch13]$ n=`echo "scale=3; 13/2" bc` [kgu@lily ch13]$ echo $n 6.500 [kgu@lily ch13]$ product=`gawk -v x=2.45 -v y=3.123 'BEGIN { printf "%.2f\n", x * y }'` [kgu@lily ch13]$ echo $product 7.65 21
위치매개변수이용 (1) 12 13 [kgu@lily ch13]$ cat greeting2.bash #!/bin/bash # Scriptname: greetings2 echo "This script is called $0." echo "$0 $1 and $2" echo "The number of positional parameters is $#" [kgu@lily ch13]$ chmod +x greeting2.bash [kgu@lily ch13]$./greeting2.bash set으로설정가능 This script is called./greeting2.bash../greeting2.bash and The number of positional parameters is 0 [kgu@lily ch13]$./greeting2.bash Tommy This script is called./greeting2.bash../greeting2.bash Tommy and The number of positional parameters is 1 [kgu@lily ch13]$./greeting2.bash Tommy Billy This script is called./greeting2.bash../greeting2.bash Tommy and Billy The number of positional parameters is 2 [kgu@lily ch13]$ cat args.bash #!/bin/bash # Scriptname: args # Script to test command line arguments echo The name of this script is $0. echo The arguments are $*. echo The first argument is $1. echo The second argument is $2. echo The number of arguments is $#. oldargs=$* set Jake Nicky Scott # Reset the positional parameters echo All the positional parameters are $*. echo The number of postional parameters is $#. echo "Good-bye for now, $1." set $(date) # Reset the positional parameters echo The date is $2 $3, $6. echo "The value of \$oldargs is $oldargs." set $oldargs echo $1 $2 $3 [kgu@lily ch13]$ chmod +x./args.bash [kgu@lily ch13]$./args.bash a b c d The name of this script is./args.bash. The arguments are a b c d. The first argument is a. The second argument is b. The number of arguments is 4. All the positional parameters are Jake Nicky Scott. The number of postional parameters is 3. Good-bye for now, Jake. The date is 05. 27., KST. The value of $oldargs is a b c d. a b c 22
위치매개변수이용 (2) 14 [kgu@lily ch13]$ cat checker.bash #!/bin/bash # Scriptname: checker # Script to demonstrate the use of special variable # modifiers and arguments name=${1:?"requires an argument" } echo Hello $name [kgu@lily ch13]$ chmod +x checker.bash [kgu@lily ch13]$./checker.bash./checker.bash: line 5: 1: requires an argument [kgu@lily ch13]$./checker.bash kgu Hello kgu 15 [kgu@lily ch13]$ set 'apple pie' pears peaches [kgu@lily ch13]$ for i in $* > do > echo $i > done apple pie pears peaches [kgu@lily ch13]$ set 'apple pie' pears peaches [kgu@lily ch13]$ for i in "$*" > do > echo $i > done apple pie pears peaches [kgu@lily ch13]$ set 'apple pie' pears peaches [kgu@lily ch13]$ for i in $@ > do > echo $i > done apple pie pears peaches [kgu@lily ch13]$ set 'apple pie' pears peaches [kgu@lily ch13]$ for i in "$@" > do > echo $i > done apple pie pears peaches 23
조건의표현과흐름제어 (1) 16 [kgu@lily ch13]$ name=tom [kgu@lily ch13]$ grep "$name" /etc/passwd [kgu@lily ch13]$ echo $? 1 [kgu@lily ch13]$ name=kgu [kgu@lily ch13]$ grep "$name" /etc/passwd kgu:x:1000:1000:kgu:/home/kgu:/bin/bash [kgu@lily ch13]$ echo $? 0 표현식평가 단일대괄호와 test 쉘은메타문자를전개하지않음 단어단위로나누어처리하므로스페이스를포함한문자열은반드시따옴표로묶어야함 이중대괄호와 test 패턴검색, 메타문자에대한해석가능 스페이스를포함한문자열은반드시따옴표로묶어야함 정확히일치하는지를검사할경우따옴표이용 논리연사자사용가능 24
조건의표현과흐름제어 (2) test 명령검사연산자 [ string1 = string2 ] [ string1 == string2 ] 참인경우 [ string1!= string2 ] string1 과 string2 는다르다 [ string ] string 은 null 이아니다 [ -z string ] string 길이가 0 이다 [ -n string ] string 길이가 0 이아니다 검사연산자 string1 과 string2 는같다 ( 양쪽에스페이스를이용해야함 ) Bash 2.x 이후에는 == 이용가능 참인경우 [ string1 a string2 ] and 연산자 (string1, string2 모두참 ) [ string1 -o string2 ] or 연산자 (string1 과 string2 둘중하나이상참 ) [!string ] not 연산자 25 검사연산자참인경우 [[ pattern1 && pattern2 ]] pattern1, pattern2 모두참 ( 정확한일치여부확인시 pattern2 ) [[ pattern1 pattern2 ]] pattern1, pattern2 모둘중하나이상참 [!pattern ] pattern과같지않다
조건의표현과흐름제어 (3) test 명령 ( 계속 ) 검사연산자참인경우 [ int1 eq int2 ] int1과 int2는같다 [ int1 ne int2 ] int1과 int2는같지않다 [ int1 gt int2 ] int1은 int2보다크다 [ int1 ge int2 ] int1은 int2보다크거나같다 [ int1 lt int2 ] int1은 int2보다작다 [ int1 le int2 ] int1은 int2보다작거나같다 검사연산자참인경우 [ file1 nt file2 ] file1이 file2보다새로운파일 ( 변경일자기준 ) [ file1 ot file2 ] file1이 file2보다오래된파일 [ file1 et file2 ] file1이 file2과동일한장치이거나같은 inode를가짐 26
조건의표현과흐름제어 (4) let 명령 C 언어와같이풍부한연산자사용가능 Bash 2.x 이후 ( ), (( )) 로치환하여사용가능 주의! 종료가 0이면성공, 1이면실패 17 [kgu@lily ch13]$ x=2 [kgu@lily ch13]$ y=3 [kgu@lily ch13]$ (( x > 2 )) [kgu@lily ch13]$ echo $? 1 [kgu@lily ch13]$ (( x < 2 )) [kgu@lily ch13]$ echo $? 1 [kgu@lily ch13]$ (( x <= 2 )) [kgu@lily ch13]$ echo $? 0 27
조건의표현과흐름제어 (5) if 명령 18 if 명령 then 명령 fi ------------------------------------------ 문자열에대해 test 사용 신양식 [[ ]] if [[ 문자열조건식 ]] then 명령 fi 숫자에대해 let 사용 신양식 (( )) if (( 수식 )) then 명령 fi [kgu@lily ch13]$ echo "Are you o.k. (y/n)?" Are you o.k. (y/n)? [kgu@lily ch13]$ read answer y [kgu@lily ch13]$ if [ "$answer" = Y -o "$answer" = y ] > then > echo "Glad to hear it." > fi Glad to hear it. [kgu@lily ch13]$ if [[ $answer == [Yy]* $answer == Maybe ]] > then > echo "Glad to hear it." > fi Glad to hear it. if 명령 then 명령 ( 들 ) else 명령 ( 들 ) fi if 명령 then 명령 ( 들 ) elif 명령 then 명령 ( 들 ) elif 명령 then 명령 ( 들 ) else 명령 ( 들 ) fi 28
조건의표현과흐름제어 (6) 파일검사연산자 검사연산자참인경우검사연산자참인경우 -b filename 블록파일 -p filename named pipe -c filename 문자파일 -O filename 파일이존재하고유효사용자 ID 소유임 -d filename 디렉토리가존재 -S filename 소켓 -e filename 파일이존재 -s filename 파일크기가 0이아니다 -f filename 파일이존재하고디렉토리가아님 -t fd 파일식별자가터미널에열려있음 -G filename 파일이존재하고유효그룹 ID 소유 -u filename setuid가설정됨 -g filename setgid가설정됨 -w filename 쓰기가능 -k filename Sticky bit이설정됨 -x filename 실행가능 -L filename 심볼릭링크 29
조건의표현과흐름제어 (7) 19 [kgu@lily ch13]$ cat perm_check.bash #!/bin/bash # Using the old style test command # filename: perm_check file=./testing if [ -d $file ] then echo "$file is a directory" elif [ -f $file ] then if [ -r $file -a -w $file -a -x $file ] then # nested if command echo "You have read,write,and execute \ permission on $file." fi else echo "$file is neither a file nor a directory. " fi [kgu@lily ch13]$ chmod +x perm_check.bash [kgu@lily ch13]$./perm_check.bash./testing is neither a file nor a directory. 20 [kgu@lily ch13]$ cat perm_check2.bash #!/bin/bash # Using the new compound operator for test (( )) # filename: perm_check2 file=./testing if [[ -d $file ]] then echo "$file is a directory" elif [[ -f $file ]] then if [[ -r $file && -w $file && -x $file ]] then # nested if command echo "You have read,write,and execute \ permission on $file." fi else echo "$file is neither a file nor a directory. " fi [kgu@lily ch13]$ chmod +x perm_check2.bash [kgu@lily ch13]$./perm_check2.bash./testing is neither a file nor a directory. 30
조건의표현과흐름제어 (8) Null 명령 21 내장명령으로서 : 으로나타냄 실제로아무런작업을하지않으며, 단지종료상태를 0 으로돌려줌 주로 if 다음에아무런작업을하지않을때이용 [kgu@lily ch13]$ cat name_grep.bash #!/bin/bash # filename: name_grep name=tom if grep "$name" databasefile >& /dev/null then : else echo "$1 not found in databasefile" exit 1 fi [kgu@lily ch13]$ chmod +x name_grep.bash [kgu@lily ch13]$./name_grep.bash not found in databasefile 22 [kgu@lily ch13]$ cat wholenum.bash #!/bin/bash # Scriptname: wholenum # Purpose:The expr command tests that the user enters an # integer # echo "Enter an integer." read number if expr "$number" + 0 >& /dev/null then : else echo "You did not enter an integer value." exit 1 fi [kgu@lily ch13]$ chmod +x wholenum.bash [kgu@lily ch13]$./wholenum.bash Enter an integer. as You did not enter an integer value. [kgu@lily ch13]$./wholenum.bash Enter an integer. 10 31
조건의표현과흐름제어 (9) case 명령 다중분기명령으로 if/elif 대신사용가능 default 행동은 *) 형식 case 변수 in value1) 명령 ( 들 ) ;; value2) *) 명령 ( 들 ) ;; esac 명령 ( 들 ) ;; 23 [kgu@lily ch13]$ cat xcolors.bash #!/bin/bash # Scriptname: xcolors echo -n "Choose a foreground color for your xterm window: " read color case "$color" in [Bb]l??) xterm -fg blue -fn terminal & ;; [Gg]ree*) xterm -fg darkgreen -fn terminal & ;; red orange) # The vertical bar means "or" xterm -fg "$color" -fn terminal & ;; *) xterm -fn terminal ;; esac echo "Out of case command" [kgu@lily ch13]$ chmod +x xcolors.bash [kgu@lily ch13]$./xcolors.bash Choose a foreground color for your xterm window: white xterm: Xt error: Can't open display: xterm: DISPLAY is not set Out of case command 32
조건의표현과흐름제어 (10) here 문서와 case 명령 주로함께사용 here 문서로메뉴구성 case 에서사용자선택검사 24 [kgu@lily ch13]$ cat here_test.bash #!/bin/bash # Scriptname: here_test echo "Select a terminal type: " cat << ENDIT 1) unix 2) xterm 3) sun ENDIT read choice case "$choice" in 1) TERM=unix export TERM ;; 2) TERM=xterm export TERM ;; 3) TERM=sun export TERM ;; esac echo "TERM is $TERM." [kgu@lily ch13]$ chmod +x here_test.bash [kgu@lily ch13]$./here_test.bash Select a terminal type: 1) unix 2) xterm 3) sun 1 TERM is unix. 33