########################

## bash 쉘 프로그래밍 ##

########################



cp /dev/null a.txt

cat /dev/null > b.txt

install -m644  /dev/null c.txt



변수 : 변수명=값 


# set


# env


# printenv


# A=10

# set | grep ^A

# unset A

# set | grep ^A

#


# echo $A

# A=10

# echo $A


export

부모프로세스  -> 자식프로세스로  변수 값을 가져갈때 사용한다.

ex) export (변수명)



SHLVL (Shell Level인듯)

# echo $SHLVL

1

# ls

  :

  :

# bash

# echo $SHLVL

2

# ls 

  :

  :




# grep PATH /etc/profile

if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then

     PATH=$PATH:$1

     PATH=$1:$PATH

export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC

[root@localhost ~]# 

[root@localhost ~]# 

[root@localhost ~]# 

[root@localhost ~]# exit

exit

[root@localhost ~]# history 10

 1112  ls /lib/

 1113  a=10

 1114  a = 10

 1115  ls=10

 1116  echo $ls

 1117  ls = 10

 1118  echo $SHLVL

 1119  ls

 1120  bash

 1121  history 10



[root@localhost ~]# !1118

echo $SHLVL

1



[root@localhost ~]# A=10

[root@localhost ~]# echo $A

10

[root@localhost ~]# bash

[root@localhost ~]# echo $SHLVL

2

[root@localhost ~]# echo $A



[root@localhost ~]# A=10

[root@localhost ~]# A = 10

-bash: A: command not found

[root@localhost ~]# A =10

-bash: A: command not found

[root@localhost ~]# A= 10

-bash: 10: command not found



[root@localhost ~]# 명령어 옵션 ...

[root@localhost l]# 명령어 옵션 ...

-bash: 명령어: command not found

--> aaa bbb ... 쓰면 aaa를 명령어로 인식한다.


[root@localhost ~]# echo $LANG

C



[root@localhost ~]# 환경변수=값 명령어 ...


[root@localhost ~]# date

Tue Apr  8 11:29:27 KST 2014

[root@localhost ~]# LANG=ko_KR.eucKR date

2014. 04. 08. (화) 11:29:41 KST


--> 환경변수=값 명령어 옵션


[root@localhost ~]# A=10

[root@localhost ~]# echo $A is $A

10 is 10

[root@localhost ~]# echo '$A' is $A

$A is 10

[root@localhost ~]# echo \$A is $A

$A is 10




[root@localhost ~]# a=`which ps`

[root@localhost ~]# b=$(which ps)

[root@localhost ~]# echo $a

/bin/ps

[root@localhost ~]# echo $b

/bin/ps



[root@localhost ~]# c=which a

-bash: a: command not found

[root@localhost ~]# c="which a"

[root@localhost ~]# echo $c

which a





==========================================

LAB> 변수에 값을 연산해서 넣는 방법

# a=100

# echo $a

100

# let "a = $a + 10"

# echo $a

110

# a=$(( $a + 200 ))

# echo $a

310




참고 : bash 프롬프트 변경하기

https://wiki.kldp.org/wiki.php/LinuxdocSgml/Bash-Prompt-HOWTO

PS1 변수가 bash 프롬프트 변수이다. 이걸 바꿔주면 프롬프트가 변한다.



위치 매개변수(positional parameter)

명령어 옵션1 옵션2 옵션3

사용법 : $0, $1, $2, $3 ...  $9 ${10}, ${11}, ${12} 

$0 -> 명령어

$1 -> 옵션1

$2 -> 옵션2

$3 -> 옵션3

:

:

10부터는 중괄호로 묶어줘야 합니다.




# yum -y groupinstall "MySQL Database"



# /etc/init.d/mysqld 


# /etc/init.d/mysqld start

# mysql

mysql> show databases;

mysql> exit


# /etc/init.d/mysqld stop







if [ 조건식 ] 

then

  조건식이 참이면 실행

fi


if [ 조건식 ] 

then

  조건식이 참이면 실행

 else

  조건식이 거짓이면 실행

fi


# i=1

# if [ $i -eq 1 ]

> then

>   echo True

> fi

True



# if [ $i -eq 0 ]

> then

>   echo True

> else

>   echo False

> fi

False




# if /usr/bin/test $i -eq 1

> then

>   echo True

> else

>   echo False

> fi

True



# if test $i -eq 1

> then

>   echo True

> else

>   echo False

> fi

True




# if (( 2 > 1 ))

> then

>   echo True

> else

>   echo False

> fi

True



# if (( ! 2 > 1 ))

> then

>   echo True

> else

>   echo False

> fi

False


--> ! 은 Not을 의미


# if [ 2 -gt 1 ]

> then

>   echo True

> else

>   echo False

> fi

True



# if [ 1 -lt 2 ]

> then

>   echo True

> else

>   echo False

> fi

True



# pwdd

-bash: pwdd: command not found

# echo $?

127



# if pwd

> then

>   echo True

> else

>   echo False

> fi

/root

True

# if pwd > /dev/null 2>&1

> then

>   echo True

> else

>   echo False

> fi

True




- mv 비교하기

# ls -l /bin/mv

-rwxr-xr-x 1 root root 78188 Jul 22  2011 /bin/mv*

# cp /bin/mv .

# cmp /bin/mv mv

# echo $?

0

# echo 123 >> mv

# ls -l mv

-rw-r--r-- 1 root root 78192 Apr  9 11:31 mv

# cmp /bin/mv mv

cmp: EOF on /bin/mv

# echo $?

1

# if cmp /bin/mv mv > /dev/null 2>&1

> then

>   echo True

> else

>   echo False

> fi

False


--> BASH에서는 echo $? 하면 숫자 값이 저장되어 있는데 바로 전 명령어가 정상 실행 됐을 경우 0이 저장되고

--> 명령어가 실패하면 0이 아닌 다른 값이 저장되어있다.

ex)



- if문은 3가지 형태의 방법을 사용한다.

if [ 조건식 ]

if /usr/bin/test 조건식    <-- 외부명령어 test를 이용

if test 조건식             <-- 내부명령어 test를 이용

if 명령어 > /dev/null 2>&1



# if cmp /bin/ls /bin/ls 

> then

>   echo True

> else

>   echo False

> fi

True



# if grep -q ^root /etc/passwd

> then

>   echo True

> else

>   echo False

> fi

True


--> grep 옵션 중 -q 는 결과를 출력하지 않게하는 옵션



- 명령어 cmp 를 이용한 if 문

# cmp 파일1 파일2 

# cmp /etc/passwd /etc/shadow

/etc/passwd /etc/shadow differ: byte 5, line 1

# cmp /bin/ls /bin/ls

# echo $?

0

# cmp /etc/passwd /etc/shadow

/etc/passwd /etc/shadow differ: byte 5, line 1

# echo $?

1



# if cmp /bin/ls /bin/ls

> then

>   echo True

> else

>   echo False

> fi

True



# if cmp /bin/ls /bin/mv

> then

>  echo True

> else

>  echo False

> fi

/bin/ls /bin/mv differ: byte 25, line 1

False

# if cmp /bin/ls /bin/mv > /dev/null 2>&1

> then

>   echo True

> else

>   echo False

> fi

False




- test 명령어를 이용한 if 문

# mv /usr/bin/test .

# if test 1 -eq 1

> then

>   echo True

> else

>   echo False

> fi

True



# mv test /usr/bin/

# if /usr/bin/test 1 -eq 1

> then

>   echo True

> else

>   echo False

> fi

True



# help test

# man test


--> test 명령어는 /usr/bin/test에도 있고

--> 아마 쉘 스크립트 자체에 test라는 명령어가 내장 되어 있을 것이다.

--> 그래서 mv 를 이용하여 /usr/bin/test 옴겨도 test 명령어가 잘 동작한다.


- 파일테스트 연산자


-e 존재하는 파일인지 

-f 일반파일인지

-d 디렉토리인지 

-r 읽기권한

-x 실행권한



=====================================================

LAB> 백업스크립트를 짜보자


백업파일명 : backup.sh

백업 디렉토리 : /backup/20140409

백업대상 디렉토리 : /etc 



# mkdir ~/bin

# cd ~/bin

# install /dev/null backup.sh

# vi backup.sh



-- backup.sh --

#!/bin/sh


today=$(date +%Y%m%d)

backupdir=/backup/$today 


if [ ! -d $backupdir ]

then

   mkdir $backupdir 

fi


cp -a /etc $backupdir

-- backup.sh --


# mkdir -m 700 /backup

# ./backup.sh

# ls /backup

20140409/

# ls /backup/20140409

etc/

# ls /backup/20140409/etc

# tree -L 2 /backup

/backup/

`-- 20140409

    `-- etc


2 directories, 0 files



# date

Wed Apr  9 12:22:40 KST 2014

# date 041012002014

Thu Apr 10 12:00:00 KST 2014


# ./backup.sh

# tree -L 2 /backup

/backup

|-- 20140409

|   `-- etc

`-- 20140410

    `-- etc


4 directories, 0 files




- 시스템의 자동화 스케줄러(cron)에 등록한다.

# chmod 700 backup.sh 

# ls -l backup.sh 

-rwx------ 1 root root 139 Apr  9 12:19 backup.sh*

# mv backup.sh /etc/cron.daily



/etc/crontab 에 이미 매일 오전 4시 2분에 /etc/cron.daily 디렉터리에 있는 스크립트들이 실행되도록 스케줄링 되어있다.




# date 040404012014.55

Fri Apr 11 04:01:55 KST 2014


# tree -L 2 /backup

/backup

|-- 20140409

|   `-- etc

|-- 20140410

|   `-- etc

`-- 20140411    <-- 생성

    `-- etc



- 용량 확인

# du -sh /etc

111M /etc

# du -sh /backup/*

111M /backup/20140409

111M /backup/20140410

111M /backup/20140411

# du -s /backup/*

112676 /backup/20140409

112676 /backup/20140410

112684 /backup/20140411





# dd if=/dev/zero of=/etc/test.dd bs=1024 count=100000


- 용량이 같다는 것은 백업이 잘 되었다는 것이다.

# date 041204012014.55

Sat Apr 12 04:01:55 KST 2014



# du -sh /etc

208M /etc

# du -sh /backup/*

111M /backup/20140409

111M /backup/20140410

111M /backup/20140411

208M /backup/20140412  


-> 원본 /etc/ 디렉터리와 백업된 디렉터리의 용량이 다르다. 권한 때문에 아마 복사가 안된 파일들이 있을 거라 예상 된다.



- test 가 끝나면 원상복귀

# rm -f /etc/test.dd 

# rdate -s time.bora.net

# mv /etc/cron.daily/backup.sh ~/bin



=====================================================



=====================================================

LAB> 쉘 스크립트를 이용하여 간단한 성적처리 프로그램을 짜시오.


파일명 : sungjuk.sh


# LANG=C

# install /dev/null sungjuk.sh

# vi sungjuk.sh



-- sungjuk.sh --

#!/bin/sh


read -p "당신의 국어점수를 입력하세요 : " kor


# if [ $kor -ge 90 -a $kor -le 100 ]


if (( $kor >= 90 && $kor <= 100 ))

then

  echo "수"

fi

-- sungjuk.sh --


=====================================================



=====================================================

LAB> 간단한 성적처리 프로그램을 짜시오.


파일명 : sungjuk.sh

출력결과 : 수,우,미,양,가 


ex) elif 를 이용해서 또다른 조건을 검사할 수 있다.


# if [ $i -eq 0 ]

> then

>   echo True 1

> elif [ $i -eq 2 ]

> then

>   echo True 2

> elif [ $i -eq 1 ]

> then

>   echo True 3

> else

>   echo False

> fi

True 3



sungjuk.sh 완성본


#!/bin/sh


read -p "당신의 국어점수를 입력하세요 : " kor


if (($kor >= 90 && $kor <= 100)) 

then

  echo "수"

elif (($kor >= 80 && $kor <= 90)) 

then

  echo "우"

elif (($kor >= 70 && $kor <= 80)) 

then

  echo "미"

elif (($kor >= 60 && $kor <= 70)) 

then

  echo "양"

else

  echo "가"

fi

=====================================================




반복문 (루프)

참고 : https://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/loops1.html


while 문


사용법 : 


 while [ 조건식 ]

 do

   참일때 실행할 명령어

 done


 while (( 조건식 ))

 do

   참일때 실행할 명령어

 done



- 무한루프


# while test pwd

> do

>   printf "."

>   sleep 1

> done



# while [ 1 ]

> do

>   printf "."

>   sleep 1

> done



# while :

> do

>   printf "."

>   sleep 1

> done



 while (( 1 ))

> do

>   printf "."

>   sleep 1

> done



- while 문을 탈출하는 방법

1. while [ 조건식 ]   <-- 조건식이 거짓일때 탈출

2. while :

   do

      break           <-- break 를 이용해서 탈출

   done



ex)

# i=0

# while :

> do

>   printf "i = %d" $i

>   printf "\n"

>   if [ $i -eq 5 ]

>   then

>     break

>   fi

>   

>   i=$(( $i + 1 ))

> done

i = 1

i = 2

i = 3

i = 4

i = 5





=====================================================

LAB> while 문을 이용해서 myshell 을 짜보자.


# install /dev/null  /bin/myshell

# vi /bin/myshell 



-- /bin/myshell --

#!/bin/sh


PROMPT="myshell> "

clear


while :

do

  printf $PROMPT

  read cmd

  

  $cmd


done


-- /bin/myshell --



# useradd -s /bin/myshell testuser

# echo 1234 | passwd --stdin testuser



# ssh testuser@localhost

testuser@localhost's password:  <-- 비번입력



myshell>pwd

/home/testuser

myshell>ls

  :

  :

--> pwd때 "/" 인 이유는 CentOS 5.8에서와 달리 Kali에서는 useradd 명령어에 -m 옵션을 주어야 홈 디렉터리가 생성된다.

--> 위에서 useradd 로 myshelluser를 만들때 -m 옵션을 안주었기 때문에 홈 디렉터리를 이동할 수 없어서 "/" 로 이동된 것이다.

--> CentOS 5.8에서는 그냥 useradd [사용자명] 으로 생성하면 된다.

--> 갑자기 Kali로 바낀 이유는 실수로 CentOS의 /bin 디렉터리를 지워버려서 복구하지 못했기 때문이다..ㅠㅠ



=====================================================