더 많은 정보를 담은 리눅스 교재를 배포했습니다. 아래의 페이지에서 리눅스 교재를 받아가세요.

https://reakwon.tistory.com/233

 

리눅스 프로그래밍 note 배포

티스토리에 리눅스에 관한 내용을 두서없이 여지껏 포스팅했었데요. 저도 제 포스팅을 찾기가 어렵기도 하고 티스토리에서 코드삽입을 하게 되면 이게 일자로 쭉 쓰여져있는 x같은 현상이 생겨

reakwon.tistory.com

쉘스크립트 기본

쉘 스크립트는 쉘에게 무슨 명령들을 실행할지 알려주는 스크립트 파일입니다. 여기서는 가장 널리쓰이는 bash 쉘을 사용하는 스크립트를 설명하도록 하겠습니다.

#!/bin/bash

스크립트 최상단에는 항상 이 구문이 적혀있어야합니다. 간단하게 hello,world라는 문자열을 출력하는 스크립트를 만들어봅시다. 파일명은 exam.sh로 정해놓고요.

#!/bin/bash

echo "hello, world"
printf "hello, world"

 

./exam.sh로 스크립트를 실행하면 되는데 혹시 실행이 되지 않는다면 실행 권한이 없어서 그런것이니까 chmod 777 exam.sh로 권한을 바꾸어주면 됩니다. 그 후 결과를 보면 echo는 개행이 되지만 printf는 개행이 되지 않는 다는 것을 알 수 있습니다. 또 C언어 처럼 문자열을 전달할 수도 있는데 포맷 문자 %s를 이용하면 됩니다.

printf "%s, %s" hello, world

 

1) 변수(Variable)

쉘스크립트에서도 변수를 사용할 수 있는데요. 변수명=값 으로 변수를 선언하고, 사용할때는 앞에 $를 붙여줍니다. 중괄호를 이용하는 방법도 있습니다. ${변수}식으로 중괄호로 묶어서 사용합니다.

#!/bin/bash

h="hello"
w="world"
echo "${h}, ${w}"

 

여기서 export를 사용하여 다른 쉘 스크립트에서 사용할 수 있게 합니다. exam.sh는 변수 선언하고 export를, exam2.sh는 그 변수를 출력하는 쉘 스크립트입니다.

#!/bin/bash
#exam.sh
export MY_VAR="reakwon"

./exam2.sh

 

#!/bin/bash
#exam2.sh
echo ${MY_VAR}

 

매개변수

프로그램에서도 실행할때 인자를 주듯 쉘 스크립트도 역시 그렇게 할 수 있습니다. 실행한 스크립트 이름은 ${0}, 그 이후는 전달받은 인자 값들입니다(${1}, ${2}, ...). 아래의 예제코드를 보면서 이해하실 수 있습니다.

#!/bin/bash


echo "script name:${0}"
echo "매개변수 갯수 :${#}"
echo "전체 매개변수  값 : ${*}"
echo "전체 매개변수 값2 : ${@}"
echo "매개변수 1 : ${1}"
echo "매개변수 2 : ${2}"

 

 

 

 

 

 

 

 

예약변수

쉘 스크립트에서 사용자가 정해서 만들 수 없는 이미 정의된 변수가 존재합니다. 그것을 예약 변수라고 하는데요. 몇가지 예약 변수를 보도록 합시다.

변수 설명
HOME 사용자 홈 디렉토리를 의미합니다.
PATH 실행 파일의 경로입니다. 여러분이 chmod, mkdir 등의 명령어들은 /bin이나 /usr/bin, /sbin에 위치하는데, 이 경로들을 PATH 지정하면 여러분들은 굳이 /bin/chmod를 입력하지 않고, chmod 입력만 해주면 됩니다.
LANG 프로그램 실행 시 지원되는 언어를 말합니다.
UID 사용자의 UID입니다.
SHELL 사용자가 로그인시 실행되는 쉘을 말합니다.
USER 사용자의 계정 이름을 말합니다.
FUNCNAME 현재 실행되고 있는 함수 이름을 말합니다.
TERM 로그인 터미널을 말합니다.

 

2) 배열(Array)

쉘 스크립트에서 배열은 1차원 배열만 지원하며 중괄호를 사용해야합니다. 배열 원소는 소괄호안에 공백으로 구분하여 줍니다. 배열 안 원소는 문자열이든 정수든 상관 없이 쓸 수 있는 특징이 있습니다.

#!/bin/bash

arr=("hello" "world" 1 2 3 4 5)

echo "배열 전체 : ${arr[@]}"
echo "배열 원소의 갯수 : ${#arr[@]}"
echo "배열 첫번째 : ${arr}, 혹은 ${arr[0]}"
echo "5번 index를 갖는 배열의 원소 : ${arr[5]}"

arr[5]="five"

echo "5번 index를 갖는 배열의 원소 : ${arr[5]}"

# 5번 원소 해제
unset arr[5]
echo "5번 원소 삭제 후"
echo "5번 index를 갖는 배열의 원소 : ${arr[5]}"
echo "6번 index를 갖는 배열의 원소 : ${arr[6]}"

 

3) 함수(Function)

다른 프로그래밍 언어와 같이 쉘 스크립트에서도 함수를 사용할 수 있습니다. 함수의 정의 형식은 아래와 같습니다. 함수명 앞 function은 써주지 않아도 무관합니다. 주의 할 점은 함수가 호출되기 전에 함수가 정의되어 있어야하며 호출할때는 괄호를 써주지 않고 호출해야한다는 점입니다.

function 함수명(){
 ... 내용 ...
}
#!/bin/bash

function func(){
        echo "func()"
}

#함수 호출
func

 

4) 비교문

쉘스크립트에서 비교문은 약간 특이합니다. 아래와 같은 형식으로 비교문을 사용할 수 있습니다. 

if [ 값1 조건 값2 ]; then
	... 작업 내용 ...
fi

조건은 -eq, -gt, -lt 등이 있는데, 자세한 것은 아래의 코드에서 보도록 합시다.

#!/bin/bash

function func(){
        a=10
        b=5

        if [ ${a} -eq ${b} ]; then
                echo "a와 b는 같다."
        fi

        if [ ${a} -ne ${b} ]; then
                echo "a와 b는 같지 않다."
        fi

        if [ ${a} -gt ${b} ]; then
                echo "a가 b보다 크다."
        fi

        if [ ${a} -ge ${b} ]; then
                echo "a가 b보다 크거나 같다."
        fi

        if [ ${a} -lt ${b} ]; then
                echo "a가 b보다 작다."
        fi

        if [ ${a} -le ${b} ]; then
                echo "a가 b보다 작거나 같다."
        fi

}

#함수 호출
func

 

 

 

 

 

 

쉘스크립트는 명령어를 다루는 스크립트이기 때문에 파일이 존재하는지, 디렉토리가 존재하는지 등 파일과 관련된 조건 여부도 조건문을 통해 알 수 있습니다. 아래는 그것을 정리한 표입니다. 그리고 앞에 느낌표(!)를 써주고 조건을 기재하면 그 조건이 false일때 참이 성립합니다.

파일 관련 조건

조건 설명
if [ -d ${변수} ]; then 
if [ ! -d ${변수} ]; then
${변수}의 디렉토리가 존재하면 참이 성립합니다. 
${변수}의 디렉토리가 존재하지 않으면 참이 성립합니다. 
if [ -e ${변수} ]; then 
if [ ! -e ${변수} ]; then 
${변수}라는 파일이 존재하면 참입니다.
${변수}라는 파일이 존재하지 않으면 참입니다.
if [ -L ${변수} ]; then 파일이 symbolic link이면 참입니다.
if [ -s ${변수} ]; then 파일의 크기가 0보다 크면 참입니다.
if [ -S ${변수} ]; then 파일 타입이 소켓이면 참입니다.
if [ -r ${변수} ]; then 파일을 읽을 수 있으면 참입니다.
if [ -w ${변수} ]; then 파일을 쓸 수 있으면 참입니다.
if [ -x ${변수} ]; then 파일을 실행할 수 있으면 참입니다.
if [ -f ${변수} ]; then 파일이 정규 파일이면 참입니다.
if [ -c ${변수} ]; then 파일이 문자 장치이면 참입니다.
if [ ${변수1} -nt ${변수2}]; then 변수1의 파일이 변수2의 파일보다 최신 파일이면 참입니다.
if [ ${변수1} -ot ${변수2}]; then 변수1의 파일이 변수2의 파일보다 최신이 아니면 참입니다.
if [ ${변수1} -ef ${변수2}]; then 변수1의 파일과 변수2의 파일이 동일하면 참입니다.

 

만약 AND조건과 OR조건을 섞어서 쓴다면 어떻게 할까요? AND는 -a, OR은 -o를 이용해서 조건을 추가할 수 있습니다.

function func(){
        a=aa
        b=bb
        if [ -f ${a} -a -d ${b} ]; then
                echo "a는 파일이고 b는 디렉토리 "
        fi
}

#함수 호출
func

 

또한 여러 조건을 걸려면, 즉, C언어에서 else if역할을 하는 것은 elif라는 것을 사용하여 else if와 똑같은 역할을 할 수 있게 해줍니다. elif[ 조건 ]; then 이런식으로 쓰시면 됩니다.

만약 반복문에서 사용하여 조건이 참일때 반복문을 멈추고 싶을때 break라는 키워드를 사용하여 반복문을 멈출 수 있습니다.

C에서 switch case와 동일한 구문을 하는 문법도 존재합니다. 아래와 같이 case문을 사용하면 됩니다. 각 case의 끝을 보면 세미콜론 2개로 종료하는 것을 볼 수 있습니다.

#!/bin/bash

case ${1} in
        "linux") echo "리눅스" ;;
        "unix") echo "유닉스" ;;
        "windows") echo "윈도우즈" ;;
        "MacOS") echo "맥OS" ;;
        *) echo "머야" ;;
esac

5) 반복문

반복문 중 for문에 대한 설명은 예제와 같이 보는 것으로 하겠습니다. 

#!/bin/bash

function func(){
        echo "사용예1"
        for i in 1 2 3 4 5
        do
                echo "${i}"
        done

        echo "사용예2"
        list="1 2 3 4 5"
        for i in ${list}
        do
                echo "${i}"
        done

        echo "사용예3"
        for i in {1..5}
        do
                echo "${i}"
        done

        echo "사용예4: 크기를 2만큼 증가시키면서 출력"
        for i in {1..5..2}
        do
                echo "${i}"
        done

        echo "사용예5: 배열을 이용"
        arr=(1 2 3 4 5)
        for i in "${arr[@]}"
        do
                echo "${i}"
        done


        echo "사용예6: C와 유사한 형식의 for문"
        for ((i=0; i<5; i++)); do
                echo "${i}"
        done
}

#함수 호출
func

 

 

 

 

 

6) 명령어의 종료 코드(exit)

만약 명령어가 실패할 경우 동작을 다르게 할것이라면 어떻게 할까요? 명령어의 종료 코드를 얻어오면 됩니다. 명령어의 종료 코드는 $?에 가장 최근 실행한 명령어의 종료 코드가 있습니다. 정상적인 종료는 0이 반환되는데, 만약 0이 아닌 값으로 반환되면 오류라고 판단하시면 됩니다. 여기에 간단한 오류를 내는 c파일(main.c)을 작성하고 gcc로 컴파일(gcc main.c)합니다. 이 c파일은 실행시 전달인자가 2개 보다 작으면 exit으로 코드 16을 반환합니다.

#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[]){
        if(argc<2){
                fprintf(stderr,"인자는 2개 이상이어야 합니다.\n");
                exit(16);
        }
}

 

그리고 쉘스크립트를 아래와 같이 수정해서 오류의 코드가 얼마인지 확인해보면 우리가 exit에 넘겨준 16이 찍히는 것을 확인할 수 있습니다.

#!/bin/bash

function func(){
        ./a.out
        echo "오류 코드 ($?)"
}

#함수 호출
func

 

./a.out에 인자를 하나 넣어서 다시 실행시켜보세요. 0이 종료코드로 반환 될 것입니다. 이렇게 이전에 명령어의 결과를 봐야하는 경우 $?으로 판단하여 분기시킬 수 있습니다.

이렇게 종료 반환 코드는 명령어 뿐만 아니라 쉘 스크립트 자체도 반환할 수 있습니다. 즉, 쉘 스크립트의 수행이 실패했는지 알려주기 위해서는 exit 명령어를 사용하면 됩니다. 아래의 예가 그 사용법을 보여줍니다. 우선 exam2.sh라는 파일을 만들어봅시다. 이 쉘 스크립트 파일은 exam.sh에서 실행할 예정입니다. 별거없이 16의 종료코드를 반환하며 끝이 납니다. 

#!/bin/bash

exit 16

 

이 쉘 파일을 exam.sh에서 실행시켜볼까요?

#!/bin/bash

function func(){
        ./exam2.sh
        echo "오류 코드 ($?)"
}

#함수 호출
func

 

확인해보면 우리가 기재했던 16이 출력되는 것을 확인할 수 있습니다.

 

 

 

반응형
블로그 이미지

REAKWON

와나진짜

,