DevOps/Linux

리눅스 - 쉘 스크립트 프로그래밍

알로그 2021. 3. 21. 19:50
반응형

리눅스 핵심 레퍼런스 책 스터디

 

쉘 스크립트 프로그래밍

스크립트를 실행하는 세 가지 방법

  1. 파일 맨 위에 #!/bin/bash 추가 후 실행 권한 부여(chmod +x myscript)
  2. 배시에 전달 (bash myscript)
  3. 현재 셀에서 '.' 또는 source 명령으로 실행 (. myscript or source myscript)

변수

변수의 모든 값은 문자열이지만, 숫자라면 셸은 적절한 때에 숫자로 취급함

> NUMBER="10"
> expr $NUMBER + 5
15

셸 내부의 어떤 변수값을 의미하는 것이라면 실행 시 에러를 방지하기 위해 따옴표를 사용할 것

> FILENAME = "My Document"
> ls $FILENAME
ls: My blahblah   # 각각(My, Document)을 두개의 인자로 봄
ls: Document blahbkah
> ls -l "$FILENAME"

변수명이 다른 문자열에 인접해 있다면 중괄호를 사용할 것

> HAT="fedora"
> echo "The plural of $HAT is $HATs"
The plural of fedora is
> echo "The plural of $HAT is ${HAT}s"
The plural of fedora is fedoras



불 값과 반환 코드

셸한테 0이라는 값은 참 또는 성공을 의미하고 그 외에는 거짓 또는 실패를 의미함
모든 리눅스 명령어는 명령이 종료되면 반환 코드 또는 종료 상태라는 정수 값을 셸에 반환함

> cat myfile
My name is Sandy Smith and
> grep Smith myfile
> echo $?
0
> grep aardvark myfile
> echo $?
1



test와 [

test 명령어는 숫자와 문자열을 포함한 간단한 불 표현들을 0 또는 1로 평가함

> test 10 -lt 5   # 10이 5보다 작은가?
> echo $?
1
> test -n "hello"   # hello의 문자열의 길이가 0이 아닌가?
> echo $?
0

정수, 문자열, 파일 속성을 확인하는 데 많이 쓰이는 test 인자는 다음과 같음

파일테스트

  • -d name : name 파일은 디렉터리인가?
  • -f name : name 파일은 일반 파일인가?
  • -L name : name 파일은 심벌릭 링크인가?
  • -r name : name 파일은 존재하며 읽을 수 있는가?
  • -w name : name 파일은 존재하며 쓸 수 있는가?
  • -x name : name 파일은 존재하며 실행 가능한가?
  • -s name : name 파일은 존재하며 그 크기가 0이 아닌가?
  • f1 -nt f2 : f1 파일은 f2 파일보다 먼저 생성됐는가?
  • f1 -ot f2 : f1 파일은 f2 파일보다 나중에 생성됐는가?

 

문자열 테스트

  • -z s1 : 문자열 s1의 길이는 0인가?
  • -n s1 : 문자열 s1의 길이는 0이 아닌가?

 

숫자 테스트

  • a -eq b : a, b가 같은가
  • a -ne b : a, b가 다른가
  • a -gt b : a가 b보다 큰가?
  • a -ge b : a가 b보다 크거나 같은가?
  • a -lt b : a가 b보다 작은가?
  • a -le b : a가 b보다 작거나 같은가?

 

test는 별칭을 가지고 있으며 대괄호 '[]' 를 통해 대체될 수 있음

> [10 -lt 15]
> echo $?
1



조건문

조건문은 다른 언어에서 이미 많이 써봤으므로 간단하게 예제정도만..

> cat script-elif
#!/bin/bash
bribe=20000
if [ `whoami` = "root" ]
then
    echo "You are the superuser"
elif [ "$USER" = "root" ]
then
    echo "You might be the superuser"
elif [ "$bribe" -gt 10000 ]
then
    echo "You can pay to be the superuser"
else
    echo "You are still a mere mortal"
fi

>./script-elif
You can pay to be the superuser



반복문

반복문도 예제정도만 참고하자

> cat sciprt-while
#!/bin/bash
i=0
while [ $i -lt 3 ]
do
    echo "$i"
    i=`expr $i + 1"
done
> ./script-while
0
1
2

for 반복문은 현재 디렉터리 내 특정 확장자를 가진 파일명 처리 같은 작업을 할 때 편리함

> cat script-for2
#!/bin/bash
for file in *.docx
do
    echo "$file is a stinky Microsoft Word file"
done
> ./sciprt-for2
letter.docx is a stinky Microsoft Word file



명령행 인자

셸 스크립트 내에서 인자를 $1, $2, $3 등과 같이 명명할 수 있음
스크립트 내에서 $1, $2를 사용하는데, 하나의 인자만 넘긴 경우에는 $2는 값이 할당되지 않음

또한 스크립트 내부에서 $#로 인자의 개수를 확인할 수 있으며 #0은 파일명으로 활용됨

> cat script-artgs2
#!/bin/bash
if [ $# -lt 2]
then
    echo "$0 error: need two arguments"
else
    echo "$1, $2
fi

> ./script-args2 Barbara
./script-args2 error: need two arguments

모든 명령행 인자를 반복하려면 특수값 $@와 for 반복문을 사용할 것(for arg in $@)



반환 코드와 함께 종료하기

exit 명령어는 스크립트를 종료하고 반환 코드를 셸로 보내고 성공하면 0을 실패하면 1을 반환함
exit를 호출하지 않으면 반환 코드는 자동으로 0임



배시로 파이핑(piping, 전달)하기

배시는 셸일 뿐 아니라 표준 입력을 읽는 bash 명령어이기도 하므로 배시로 전송하여 실행할 수 있음

> echo wc -l myfile
wc -l myfile
> echo wc -l myfile | bash
18 myfile

웹 사이트에서 photo1.jpg부터 photo100.jpg까지 다운로드 받는다고 가정하자

> for i in `seq 1 100`
do
    echo wget http://example.com/photo$i.jpg
done
wget http://example.com/photo1.jpg
wget http://example.com/photo2.jpg
...
wget http://example.com/photo100.jpg

명령어가 제대로 되는지 확인한 후 bash로 파이핑하면 다운로드가 완료됨

> for i in `seq 1 100`
do
    echo wget http://example.com/photo$i.jpg
done | bash
반응형