########################
## 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 디렉터리를 지워버려서 복구하지 못했기 때문이다..ㅠㅠ
=====================================================