Post

이것이 리눅스다. - 7. 셸 스크립트 프로그래밍

한빛 미디어의 이것이 리눅스다. 책을 정리한 자료입니다.


7.1 셸의 기본

  • 셸은 사용자가 입력한 명령을 해석해 커널에 전달하거나, 커널의 처리 결과를 사용자에게 전달하는 역할을 합니다.

7.1.1 CentOS의 bash셸

CentOS에서 기본적으로 사용하는 셸의 이름은 bash이며 bash셸이라고 읽습니다.

  • Alias 기능(명령어 단축 기능)
  • History 기능
  • 연산 기능
  • Job Control 기능
  • 자동 이름 완성 기능(Tab)
  • 프롬프트 제어 기능
  • 명령 편집 기능

7.1.2 환경 변수

셸은 여러 가지 환경 변수를 갖습니다. 설정된 환경 변수는 ‘echo$환경 변수이름’형식으로 실행하면 확인할 수 있습니다.

환경 변수 값을 변경하려면 ‘export 환경변수=값’ 형식을 실행합니다.
‘printenv’명령어를 실행하면 출력됩니다.


7.2 셸 스크립트 프로그래밍 실습

  • 리눅스의 많은 부분이 셸스크립트로 작성되었기에 배워두면 좋다고 합니다.

7.2.1 셸 스크립트 작성과 실행

셸 스크립트 작성

1
vi name.sh

첫 번째줄의 의미는 bash를 사용하겠다는 의미로 꼭 써야합니다.

1
sh name.sh //실행

7.2.2 변수

  • 변수의 기본
    • 셸 스크립트에서는 미리 선언하는 것이 아닌 처음 변수에 값이 할당되면 자동으로 변수가 생성된다.
    • 변수에 넣는 모든 값은 ‘문자열’ 취급 -> 숫자를 넣어도 문자열 취급
    • 대소문자 구분, 대입 시 ‘=’ 좌우에 공백이 없어야함.

변수의 입력과 출력

’$’라는 문자가 들어간 글자를 출력하려면 ‘‘로 묶어주거나 앞에 ‘'를 붙여야합니다. 또한, ““로 변수를 묶거나 묶지않아도 됩니다.

1
2
3
4
5
6
7
8
9
10
#!/bin/sh
myvar="Hi Woo"
echo $myvar     //정상출력
echo "$myvar"   //정상출력
echo '$myvar'   //'$myvar'출력
echo \$myvar    //$를 문자열 취급하여 $myvar출력
echo input plz :
read myvar
echo '$myvar' = $myvar
exit 0

숫자 계산

  • 기본적으로 변수에 넣은 값은 모두 문자열 취급하므로 ‘expr’키워드를 사용해야 합니다.
  • (`) 키로 수식을 묶어야 한다고 합니다.
  • 괄호를 사용하려면 ‘'를 붙여줘야한다고 합니다.
  • 사칙연산 중 곱하기(*)에도 ‘'를 붙여줘야한다고 합니다.
1
2
3
4
5
6
7
8
9
#!/bin/sh
num1=100
num2=$num1+200
echo $num2
num3=`expr $num1 + 200`
echo $num3
num4=`expr \( $num1 + 200 \) / 10 \* 2`
echo $num4
exit 0

에러가 2번 났는데 주의점이 있습니다.

  • 첫 번째는 ‘ 따옴표가 1번옆에 있는 ` 이걸 써야한다는 점
  • 두 번째는 괄호에서 ‘(‘ 이부분 에 붙여 쓰면 에러납니다. 그래서 한 칸 띄고 써줘야합니다.

파라미터 변수

  • 파라미터 변수는 ‘$0’, ‘$1’ 등의 형태를 갖습니다. 이는 실행하는 명령의 부분 하나하나를 변수로 지정한다는 의미입니다.
  • 예를 들어 ‘yum -y install gftp’는 yum은 $0, -y는 $1… 이런 식입니다.
1
2
3
4
5
6
7
8
vi paravar.sh

#!/bin/sh
echo "first excute file name is <$0>"
echo "first parameter is <$1>, second parameter is <$2>"
echo "all of parameter is <$*>"
exit 0

7.2.3 if문과 case문

  • if문의 주의점은 [조건]의 각 단어는 모두 공백이 있어야 합니다.
1
2
3
4
5
6
7
8
9
10
vi if1.sh

#!/bin/sh
if [ "woo" = "woo" ]
then
        echo "true"
fi
exit 0

sh if1.sh

뒤에는 vi로 문서여는 명령어와 sh로 실행하는 명령어를 적지 않겠습니다. 모두 직접해봤으니 안되는 예제는 없습니다.

if else문

1
2
3
4
5
6
7
8
#!/bin/sh
if [ "woo" != "woo" ]
then
        echo "true"
else
        echo "false"
fi
exit 0

조건에 들어가는 비교 연산자

1
2
3
4
5
6
7
8
9
#!/bin/sh
if [ 100 -eq 200 ]
then
        echo "100 equal 200"
else
        echo "100 nequal 200"
fi
exit 0

파일과 관련된 조건

1
2
3
4
5
6
7
8
9
10
#!/bin/sh
fname=/lib/systemd/system/httpd.service
if [ -f $fname ]
then
        head -5 $fname
else
        echo "not install web service"
fi
exit 0

case~esac문

  • if문은 참과 거짓이라는 두 가지 경우만 사용할 수 있습니다. 2중 분기인 if문과 다르게 다중분기인 case문을 사용해봅니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
case "$1" in
        start)
                echo "start!";;
        stop)
                echo "stop!";;
        restart)
                echo "restart!";;
        *)
                echo "nothing";;
esac
exit 0

사용방법은

1
2
3
4
sh case1.sh stop
sh case1.sh start
sh case1.sh restart
sh case1.sh 아무글자

AND, OR 관계 연산자

  • and는 ‘-a’ 또는 ‘&&’를 사용하며 or는 ‘-o’ 또는 ‘ ‘를 사용한다.
1
2
3
4
5
6
7
8
9
#!/bin/sh
echo "input filename"
read fname
if [ -f $fname ] && [ -s $fname ] ; then
        head -5 $fname
else
        echo "found not file or size is zero"
fi
exit 0

7.2.4 반복문

for~in문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for i in 1 2 3  4 5 6 7 8 9 10
do
        hap=`expr $hap + $i`
done
echo "sum of 1 ~ 10" : $hap
exit 0

//현재 디렉터리에 있는 셸 스크립트 파일 이름과 앞 3줄 출력
for fname in $(ls *.sh)
do
    echo "-----$fname-----"
    head -3 $fname
done
exit 0

  • 정말 불편하다..

while문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh
while [ 1 ]
do
        echo "CentOS 7"
done
exit 0

//1부터 10까지 합
#!/bin/sh
hap=0
i=1
while [ $i -le 10 ]
do
        hap=`expr $hap + $i`
        i=`expr $i + 1`
done
echo "sum of 1 ~ 10 : " $hap
exit 0


  • for문보다는 낫네..

until문

  • until문은 while문과 용도가 거의 같지만, 조건식이 거짓인 동안 계속 반복합니다.
  • 1~10 합 코드의 while문을 다음과 같이 바꾸면 됩니다. until [ $i -gt 10 ]

break,continue,exit,return문

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
while [ 1 ] ; do
        read input
        case $input in
          b | B)
           break;;
          c | C)
            echo " continue is return to while"
            continue;;
          e | E)
            echo " exit is exit function"
            exit 1;;
        esac;
done
echo "input beak"
exit 0

7.2.4 기타 알아둘 내용

사용자 정의 함수

1
2
3
4
5
6
7
8
9
10
#!/bin/sh
myFunction(){
        echo "in function"
        return
}
echo    "start program"
myFunction
echo    "exit program"
exit 0

함수 파라미터 사용

  • 함수 안에서는$1 , $2 …로 사용합니다.
1
2
3
4
5
6
7
8
#!/bin/sh
hap (){
echo `expr $1 + $2`
}
echo "10 + 20"
hap 10 20
exit 0

eval

  • 문자열을 명령문으로 인식하고 실행합니다.
1
2
3
4
5
6
#!/bin/sh
str="ls -l anaconda-ks.cfg"
echo $str
eval $str
exit 0

export

  • 외부 변수로 선언하여 다름 프로그램에서도 사용할 수 있게 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
vi exp1.sh

#!/bin/sh
echo $var1
echo $var2
exit 0

vi exp2.sh

!/bin/sh
var1="local var"
export var2="export var"
sh exp1.sh
exit 0

sh exp2.sh

printf

  • c 언어의 printf() 함수와 비슷하게 형식을 지정해서 출력할 수 있습니다.
1
2
3
4
5
6
#!/bin/sh
var1=100.5
var2="fun...linux"
printf "%5.2f \n\n \t %s \n" $var1 "$var2"
exit

set과 $(명령어)

  • 리눅스 명령어를 결과로 사용하려면 ‘$(명령어)’ 형식을 사용해야 합니다. 또 결과를 파라미터로 사용하고자 할 때는 ‘set’ 명령어와 함게 사용합니다.
1
2
3
4
5
#!/bin/sh
echo "today is $(date)"
set $(date)
echo "today is $4"
exit 0

shift

  • 파라미터 변수를 왼쪽으로 한 단계씩 아래로 쉬프트(이동)시킵니다.

  • 기존 코드의 문제점 ```console #!/bin/sh myfunc(){ echo $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 } myfunc AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK exit 0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
![](/assets/img/sample/Linux/ThisisLinux/C7/result5.JPG)  

- AAA0, AAA1이 나온 이유는 $10을 $1 + 0으로 인식하기 때문입니다. 따라서 shift연산을 해줘야합니다.

- 개선한 코드

```console
#!/bin/sh
myfunc(){
        str=""
        while [ "$1" != "" ] ; do
                str="$str $1"
                shift
        done
        echo $str
}
myfunc AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK
exit 0


다 따라치느라 너무 힘들었다.. 후 기본적인 문법지식이 있으면 셸 문법봐도 대강 이해할 것이라 생각합니다. 제가 그랬으니까요..

This post is licensed under CC BY 4.0 by the author.