2013. 11. 19. 14:23ㆍ99. 정리전 - IT/13. Unix 얇팍지식
츌처 : http://www.insford.com/wiki/Wiki.jsp?page=Shell%20Script
목차
들어가며#
Shell Script란?#
쉘스크립트에 대한 다음백과사전의 정의를 보면 다음과 같이 작성되어 있다.간단하게 얘기하자면 쉘에서 명령어를 이용하여 여러가지 작업들을 처리할 수 있는데, 동일한 작업들이 반복적으로 일어나게 된다면 매번 같은 명령어를 직접 입력하지 않고 파일에 기록하여 편리하게 이용하는것이 쉘스크립트 입니다.
쉘스크립트 에디터 이클립스 플러그인#
- 다운로드 http://sourceforge.net/projects/shelled/
- 인스톨방법 http://sourceforge.net/apps/trac/shelled/wiki/ShellEd-Installation-Instructions
참고내용 URL#
쉘 프로그래밍 시작하기#
쉘 스크립트 작성#
쉘 스크립트는 기본적으로 vi에디터를 이용하여 작성한다. 아직 vi에디터에 익숙하지 않다면 다음 링크를 확인하자. 자주쓰는 vi에디터 명령어
상단부분은 항상 #! 으로 시작한다. #! 뒤에는 해당스크립트를 실행할 인터프리터의 절대경로와 실행옵션을 지정한다. 보통 #!/bin/bash, #!/bin/sh, #!/bin/csh 등을 많이쓴다.
그 외 기본 명령어들
명령어 | 설명 |
---|---|
#텍스트 | 주석 |
clear | 화면 지우기 |
echo 텍스트 or 변수 | 화면에 텍스트 출력 |
- 샘플
#!/bin/bash # 주석입니다. clear echo Hello World #하나의 라인에서 2개의 명령어 실행 할 때에는 ; 로 구분하여 사용한다. date;echo date
echo 커맨드옵션#
echo [옵션]] [텍스트, 변수 등]]옵션
- -n 출력 후 줄바꿈 안함
- -e 다음과 같은 문자를 텍스트에서 사용 가능하게한다.
\a | alert (bell) |
\b | backspace |
\c | suppress trailing new line |
\n | new line |
\r | carriage return |
\t | horizontal tab |
\ \ | backslash |
사용자 변수#
기본적으로 변수명=값 와 같은 형태로 작성한다.- 변수명에 값을 할당할때 공백을 넣지 않는다.
- 대소문자를 구분한다.
- 변수명에 ? * 문자는 사용금지
- 샘플
#!/bin/bash test=testValue1 test2=$test test3=testValue3 echo test=$test echo test2=$test2 echo test3=$test3
- 변수명과 텍스트를 붙여쓰고싶을때
echo "텍스트"$변수명"텍스트"
시스템변수#
변수명 | 설명 |
---|---|
BASH | 쉘이름 |
BASH_VERSION | 쉘 버젼 |
COLUMNS | 컬럼 |
LINES | 라인 |
HOME | 홈디렉토리 |
LOGNAME | 로그인명 |
OSTYPE | OS타입 |
PATH | 패스설정값 |
PS1 | prompt설정값 |
PWD | working디렉토리 |
SHELL | 쉘이름 |
USERNAME | 현재피씨로로그인한유저 |
계산식 사용하기#
expr 값1 연산자 값2해당 공식을 계산해서 화면에 출력한다.
expr 1 + 3 expr 2 - 1 expr 10 / 2 expr 20 % 3 expr 10 \* 3 echo `expr 6 + 3`
- 변수에 넣거나, 화면에 계산값을 출력할 때에는 ` 을 이용하여 작성한다. 키보드에 `는 ~표시와 같은위치에 있다.
sum=`expr 1 + 5` echo $sum echo `expr 5 + 1` # 계산값이 출력 됨. echo expr 5 + 1 # 이부분은 다음과 같이 그대로 출력된다. "expr 5 + 1"
quote 출력규칙#
" | \, $ 문법이 사용 가능하다. |
' | \, $ 문법을 무시하고 그대로 출력한다. |
` | `안에있는 커맨드를 실행하여 출력한다. |
- 샘플
id=insford echo "Hello $id" # Hello insford 출력 echo 'Hello $id' # Hello $id 출력 echo 'expr 1 + 3' # expr 1 + 3 출력 echo `expr 1 + 3` # 4 출력
종료상태#
echo $?위 명령어를 실행하면 최근에 실행했던 명령어의 종료상태를 알 수 있다.
0 - 성공
1~255 - 실패
- 샘플
#!/bin/bash expr 1 + 3 echo $? # 성공이므로 0이 출력 exprrr 1 + 3 echo $? # command not found인 127이 출력된다.
에러코드에 대한 내용은 다음 링크를 참조하자 http://tldp.org/LDP/abs/html/exitcodes.html
입력값 받기#
read 변수사용자로부터 입력값을 받는 명령어이다.
- 샘플
#!/bin/bash echo "input your name" read name echo "your name is $name"
매개변수#
함수를 호출할 때나, 쉘스크립트파일을 실행할 때 뒤에 띄어쓰기로 구분하여 매개변수를 전달 할 수 있다.
예제 | 설명 |
---|---|
$0 | 쉘스크립트이름 |
$# | 매개변수의 개수 |
$* | 매개변수들을 모아놓은 문자열 |
$1 ~ $n | 매개변수 |
다음과 같이 매개변수 전달 했을 경우 #] sh xxxx.sh param1 param2
#!/bin/bash echo $0 # xxxx.sh echo $# # 2 echo $* # param1 param2 echo $1 # param1 echo $2 # param2
변수 내용 조작하기#
예제 | 설명 |
---|---|
${variable:-default} | 변수가존재하지 않으면 default로 대체한다. |
${#variable} | variable의 length를 얻는다. |
${variable%word} | variable의 끝에서부터 word와 첫번째로 일치하는 부분을 제거한다. |
${variable | variable의 끝에서부터 word와 마지막으로 일치하는 부분을 제거한다. |
${variable#word} | variable의 시작에서부터 word와 첫번째로 일치하는 부분을 제거한다. |
${variable##word} | variable의 시작에서부터 word와 마지막으로 일치하는 부분을 제거한다. |
word에는 와일드카드(*) 를 사용할 수 있다.
#!/bin/bash abc="I am a boy" echo ${abc:-default} # I am a boy echo ${abcd:-default} # default - abcd변수가 없어서 default가 출력된다. echo ${#abc} # 10 echo ${abc%a*} # I am echo ${abc%%a*} # I echo ${abc#*a} # m a boy echo ${abc##*a} # boy
구조적 프로그래밍#
조건절 입력 ( test 명령 )#
if문 등에서의 조건절에서 참과 거짓을 구분할 때 test 명령이 다음과 같은 형태로 쓰인다.문자열비교 test "aa" = "aa"
test명령은 [ 명령 ] 과 같은 형태로 사용할 수 있다.
[ "aa" = "aa" ]
AND 와 OR 조건은 다음과 같은 형태로 사용이 가능하다.
[ "aa" = "aa" ] && [ "bb" = "bb" ] [ "aa" = "aa" ] || [ "bb" = "bb" ]
- 문자열 비교 조건
식 | 설명 |
---|---|
[ string ] | 빈문자열이 아니면 true |
[ string1 = string2 ] | 문자열이 같으면 true |
[ string1 != string2 ] | 문자열이 다르면 true |
[ -n string ] | 문자열이 null이 아니면 true |
[ -z string ] | 문자열이 null이면 true |
- 산술 비교 조건
식 | 설명 |
---|---|
[ expr1 -eq expr2 ] | 두 표현식이 같으면 true |
[ expr1 -ne expr2 ] | 두 표현식이 같지 않으면 true |
[ expr1 -gt expr2 ] | expr1 > expr2 이면 true |
[ expr1 -ge expr2 ] | expr1 >= expr2 이면 true |
[ expr1 -lt expr2 ] | expr1 < expr2 이면 true |
[ expr1 -le expr2 ] | expr1 <= expr2 이면 true |
[ ! expr ] | true이면 false, false이면 true |
[ expr1 -a expr2 ] | expr1 AND expr2 의 결과 |
[ expr1 -o expr2 ] | expr1 OR expr2 의 결과 |
- 파일 비교 조건
식 | 설명 |
---|---|
[ -b FILE ] | FILE 이 블럭 디바이스이면 true |
[ -c FILE ] | FILE 이 문자 디바이스이면 true |
[ -d FILE ] | FILE 이 디렉토리이면 true |
[ -e FILE ] | FILE 이 존재하면 true |
[ -f FILE ] | FILE 이 존재하고 정규파일이면 true |
[ -g FILE ] | FILE 이 set-group-id 파일이면 true |
[ -h FILE ] | FILE 이 심볼릭 링크이면 true |
[ -L FILE ] | FILE 이 심볼릭 링크이면 true |
[ -k FILE ] | FILE 이 Sticky bit 가 셋팅되어 있으면 true |
[ -p FILE ] | True if file is a named pipe. |
[ -r FILE ] | 현재 사용자가 읽을 수 있는 파일이면 true |
[ -s FILE ] | 파일이 비어있지 않으면 true |
[ -S FILE ] | 소켓 디바이스이면 true |
[ -t FD ] | FD 가 열려진 터미널이면 true |
[ -u FILE ] | FILE 이 set-user-id 파일이면 true |
[ -w FILE ] | 현재 사용자가 쓸 수 있는 파일(writable file) 이면 true |
[ -x FILE ] | 현재사용자가 실행할 수 있는 파일(Executable file) 이면 true |
[ -O FILE ] | FILE 의 소유자가 현재 사용자이면 true |
[ -G FILE ] | FILE 의 그룹이 현재 사용자의 그룹과 같으면 true |
[ FILE1 -nt FILE2 ] | FILE1이 FILE2 보다 새로운 파일이면 ( 최근파일이면 ) true |
[ FILE1 -ot FILE2 ] | FILE1이 FILE2 보다 오래된 파일이면 true |
[ FILE1 -ef FILE2 ] | FILE1 이 FILE2의 하드링크 파일이면 true |
if문#
#!/bin/bash if [ 조건 ] then #조건이 참일때 else #조건이 거짓일때 fi # # if - elseif 문 if [ 조건1 ] then #조건1 이 참일때 elif [ 조건2 ] #조건1이 거짓이고, 조건2가 참일때 else #조건1, 2가 거지일때 fi
case문#
case $1 in "a" ) echo '$1 is a' ;; # $1이 a일때 "b" ) echo '$1 is b' ;; # $1이 b일때 * ) echo 'do not have condition' ;; # * 이므로 $1이 어떤것이라도 출력된다. java의 default: 와 같음 esac
for문#
for i in 리스트
list="a1 a2 a3 a4" for i in $list do echo $i # a1, a2 .. 각 값이 차례대로 출력된다. done # 다음처럼 리스트에 명령어 결과를 이용 할 수 있다. for file in `ls -a` do echo $file done
while문#
i=1 while [ $i -lt 10 ] # 조건절 i < 10 이면 do echo $i i=`expr $i + 1` # i = i + 1 done
Functions#
쉘 스크립트에서는 다음과 같이 함수를 만들어 사용할 수 있다.
#!/bin/bash test_function() #함수명() { echo "test functions" echo "arg1=$1" # 함수를 호출할때 인자값을 입력하여 함수 내에서 사용이 가능하다. return 0; # 함수 내에서 리턴값을 사용 가능하다. 0 ~ 255 까지의 값 (0일경우 성공을 나타낸다) } test_function 1 # 함수를 호출하면서 1이라는 인자값을 입력하였다. echo "return=$?" # 리턴값 출력
- 결과는 다음과 같다.
[insford1@j64-003 ~]$ sh test.sh test functions arg1=1 return=0
다음과 같은 방법으로도 함수선언이 가능하다.
#!/bin/bash function test_function { # function 함수명 echo "test_function" local LOCAL_V="local variable" #변수선언시 앞에 local 을 붙이면 해당 함수 내에서만 쓰는 변수가 생성된다. V="variable" echo "test_function LOCAL_V=$LOCAL_V" echo "test_function V=$V" } test_function echo "LOCAL_V=$LOCAL_V" # local로 선언되었기 때문에 여기서는 출력이 되지 않는다. echo "V=$V"
- 결과확인
[insford1@j64-003 ~]$ sh test.sh test_function test_function LOCAL_V=local variable test_function V=variable LOCAL_V= V=variable
디버깅 방법#
쉘스크립트 디버깅 방법을 소개합니다. 일단 예제소스를 먼저 보시면..
# 에러발생스크립트 i=1 while [ $i -lt 10 ] do echo $i i=`$i + 1` # 에러지점 i=`expr $i + 1` 과같이 사용해야한다. done
위 스크립트를 실행하면 다음과 같이 에러메세지가 발생합니다.
1 test.sh: line 8: 1: command not found test.sh: line 5: [: -lt: unary operator expected
1까지만 출력이되고 덧셈을 하려할 때 에러가납니다.
라인만 가지고는 정확히 어느부분에서 에러가나는지 확인하는게 쉽지 않습니다. 하지만 스크립트를 실행할 때 다음과 같은 옵션을 주면 디버깅이 쉬워집니다.
옵션 | 설명 |
---|---|
-v | 에러메세지가 발생한 라인을 출력한다. |
-x | 각각의 명령이 일어나는 부분을 출력하여준다. |
- -v 옵션으로 실행하였을 때 #] sh -v xxxx.sh
i=1 while [ $i -lt 10 ] do echo $i i=`$i + 1` done 1 $i + 1 test.sh: line 8: 1: command not found test.sh: line 5: [: -lt: unary operator expected
스크립트의 소스코드 및 출력값이 나오고 맨 마지막에 에러난 라인이 나와 에러가 난 부분의 소스를 확인이 가능하다.
- -x 옵션으로 실행하였을 때 #] sh -x xxxx.sh
+ i=1 + '[' 1 -lt 10 ']' + echo 1 1 ++ 1 + 1 test.sh: line 8: 1: command not found + i= + '[' -lt 10 ']' test.sh: line 5: [: -lt: unary operator expected순차적으로 명령이 일어난 부분을 출력해주어, 1 + 1 을 계산할 때 에러가나고, 조건절에서 에러가 나는 것을 알 수 있다.
두 옵션을 적절히 사용하면 디버깅에 많은 도움이 될 듯 싶다.