Bash Shell

CentOS의 기본 쉘은 Bash(Bourne Again SHell : “배쉬 쉘”)


Bash Shell의 특징

  • Alias 기능(명령어 단축 기능)

  • History 기능(↑/↓)

  • 연산 기능

  • Job Control 기능

  • 자동 이름 완성 기능(Tab키)

  • 프롬프트 제어 기능

  • 명령 편집 기능


Shell의 명령문 처리 방법

  • (프롬프트) 명령어 [옵션…] [인자…]

  • 예) # rm -rf /sun



환경 변수

echo $환경변수이름으로 확인 가능

[sun@localhost ~]$ echo $HOME
/home/sun


export 환경변수=값으로 환경 변수의 값 변경 가능 - 단, 로그인 세션에서만 유지

[sun@localhost ~]$ echo $WOW
[sun@localhost ~]$ export WOW=1234
[sun@localhost ~]$ echo $WOW
1234


주요 환경 변수

환경 변수 설명
HOME 현재 사용자의 홈 디렉토리 /home/sun
LANG 현재 지원되는 언어 ko_KR.UTF-8
TERM 로그인 터미널 타입 xterm
USER 현재 사용자 이름 sun
COLUMNS 현재 터미널의 컬럼 수 80
PS1 1차 명령 프롬프트 변수 [\u@\h \W]\$
BASH bash 셀의 경로 /bin/bash
HISTFILE 히스토리 파일 경로 /home/sun/.bash_history
HOSTNAME 호스트의 이름 localhost.localdomain
LOGNAME 로그인 이름 sun
MAIL 메일 보관 경로 /var/spool/mail/sun
PATH 실행 파일을 찾는 디렉터리 경로 /usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/sun/.local/bin:/home/sun/bin
PWD 사용자의 현재 작업 디렉터리 /home/sun
SHELL 로그인해서 사용중인 쉘 /bin/bash
LINES 현재 터미널 라인 수 24
PS2 2차 명령 프롬프트(대개 >) >
BASH_VERSION bash 버전 4.2.46(2)-release
HISTSIZE 히스토리 파일에 저장되는 개수 1000
OSTYPE 운영체제 타입 linux-gnu



쉘 스크립트 프로그래밍 특징

  • C언어와 유사하게 프로그래밍 가능

  • 변수, 반복문, 제어문 등의 사용이 가능

  • 별도로 컴파일하지 않고 텍스트 파일 형태로 바로 실행

  • vi 등으로 작성이 가능

  • 리눅스의 많은 부분이 쉘 스크립트로 작성되어 있음



쉘 스크립트의 작성과 실행

작성시

  • vi로 작성

  • 쉘 스크립트 파일의 확장명은 되도록 *.sh


작성 내용

[sun@localhost ~]$ vi name.sh
#!/bin/sh
echo "호스트명": $HOSTNAME
exit 0
  • 첫줄 #!/bin/sh → 사용할 언어 선택(sh 쉘)


실행 방법 1. sh <스크립트파일>

[sun@localhost ~]$ ll
합계 4
-rw-rw-r--. 1 sun sun 48 10월 15 11:33 name.sh
[sun@localhost ~]$ sh name.sh
호스트명: localhost.localdomain


실행 방법 2. 실행 가능 속성 부여 chmod +x <스크립트파일>./<스크립트파일>로 실행

[sun@localhost ~]$ chmod +x name.sh
[sun@localhost ~]$ ll
합계 4
-rwxrwxr-x. 1 sun sun 48 10월 15 11:33 name.sh
[sun@localhost ~]$ ./name.sh
호스트명: localhost.localdomain


스크립트 파일의 속성을 755로 변경해주면 모든 사용자가 스크립트를 사용할 권한이 생김

스크립트 파일을 /user/local/bin 디렉토리에 복사해두면 모든 사용자가 접근할 수 있음

보안상 root 권한으로 수행



변수의 기본

  • 사용 전 미리 선언하지 않음. 처음 값이 할당되면서 자동으로 변수가 생성

  • 모든 변수는 문자열(String)로 취급

  • 대소문자를 구분

  • 변수 대입시 = 좌우에 공백이 없어야 함

  • 값에 띄어쓰기(공란)가 있다면, " / ' 등으로 묶어줘야 함

  • $ 문자가 들어간 글자를 사용하려면 ' '로 묶어주거나 앞에 \를 붙이면 됨

[sun@localhost ~]$ vi var1.sh
#!/bin/sh
myvar="Hello Sun"
echo $myvar
echo "$myvar"
echo '$myvar'
echo \$myvar
echo 값 입력 :
read myvar
echo '$myvar' = myvar
exit 0
[sun@localhost ~]$ sh var1.sh
Hello Sun
Hello Sun
$myvar
$myvar
값 입력 :
아무 값을 입력해보고 있음
$myvar = 아무 값을 입력해보고 있음



숫자 계산

  • 변수에 대입된 값은 모두 문자열로 취급

  • 변수에 들어있는 값을 숫자로 해서 +, -, *, / 등의 연산을 하려면 `expr (연산식)`을 사용

  • 수식에 괄호()나 곱하기*의 경우 그 앞에 꼭 역슬래쉬\를 붙임

[sun@localhost ~]$ vi num1.sh
#!/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
[sun@localhost ~]$ sh num1.sh
100+200
300
60



파라미터(Parameter) 변수

  • 파라미터 변수는 $0, $1, $2…의 형태

  • 전체 파라미터는 $*

[sun@localhost ~]$ vi para1.sh
#!/bin/sh
echo "실행파일 이름은 <$0>"
echo "첫 번째 파라미터 <$1>"
echo "두 번째 파라미터 <$2>"
echo "세 번째 파라미터 <$3>"
echo "전체 파라미터 <$*>"
exit 0
[sun@localhost ~]$ sh para1.sh 값1 값2 값3
실행파일 이름은 <para1.sh>
첫 번째 파라미터 <값1>
두 번째 파라미터 <값2>
세 번째 파라미터 <값3>
전체 파라미터 <값1 값2 값3>


파라미터변수 $0 $1 $2 $3
명령어1 yum -y install gftp
명령어2 para1.sh 값1 값2 값3



조건문 - 기본 if문

형식

if [ 조건 ]    
then           
  참일경우 실행
fi

” 조건 “의 사이의 각 단어에는 모두 공백이 있어야 함

[sun@localhost ~]$ vi if1.sh
#!/bin/sh
if [ "sun" = "sun" ]
then
  echo "참입니다"
fi
exit 0
[sun@localhost ~]$ sh if1.sh
참입니다



조건문 - if~else문

형식

if [ 조건 ]    
then           
  참일경우 실행
else
  거짓인 경우 실행
fi

중복 if문을 위해서 else if가 합쳐진 elif문도 사용할 수 있음

[sun@localhost ~]$ vi if2.sh
#!/bin/sh
if [ "sun" != "sun" ]
then
  echo "참입니다"
else
  echo "거짓입니다"
fi
exit 0
[sun@localhost ~]$ sh if2.sh
거짓입니다



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

문자열 비교

문자열 비교 결과
“문자열1” = “문자열2” 두 문자열이 같으면 참
“문자열1” != “문자열2” 두 문자열이 같지 않으면 참
-n “문자열” 문자열이 NULL(빈 문자열)이 아니면 참
-z “문자열” 문자열이 NULL(빈 문자열)이면 참


산술 비교

산술 비교 결과
수식1 -eq 수식2 두 수식(또는 변수)이 같으면 참
수식1 -ne 수식2 두 수식(또는 변수)이 같지 않으면 참
수식1 -gt 수식2 수식 1이 크면 참
수식1 -ge 수식2 수식 1이 크거나 같으면 참
수식1 -lt 수식2 수식 1이 작으면 참
수식1 -le 수식2 수식 1이 작거나 같으면 참
!수식 수식이 거짓이라면 참
[sun@localhost ~]$ vi if3.sh
#!/bin/sh
if [ 100 -eq 200 ]
then
  echo "100과 200은 같음"
else
  echo "100과 200은 다름"
fi
exit 0
[sun@localhost ~]$ sh if3.sh
100과 200은 다름



파일과 관련된 조건

파일 조건

파일 조건 결과
-d 파일명 디렉터리면 참
-e 파일명 존재하면 참
-f 파일명 일반파일이면 참
-g 파일명 set-group-id가 설정되어있으면 참
-r 파일명 읽기 가능이면 참
-s 파일명 크기가 0이 아니면 참
-u 파일명 set-user-id가 설정되어있으면 참
-w 파일명 쓰기 가능이면 참
-x 파일명 실행 가능이면 참
[sun@localhost ~]$ pwd
/home/sun
[sun@localhost ~]$ ls
if1.sh  if2.sh  if3.sh  name.sh  num1.sh  para1.sh  var1.sh
[sun@localhost ~]$ vi if4.sh
#!/bin/bash
fname=/home/sun/num1.sh
if [ -f $fname ]
then
   head -3 $fname
else
   echo "num1.sh 파일이 없습니다."
fi
exit 0
[sun@localhost ~]$ sh if4.sh
#!/bin/sh
num1=100
num2=$num1+200



조건문 - case~esac문(1)

  • if문은 참 또는 거짓일 경우에만 사용 가능(이중분기)
  • case문은 여러가지 경우의 수가 있다면 사용하면 좋음(다중분기)
[sun@localhost ~]$ vi case1.sh
#!/bin/sh
case "$1" in
  start)
    echo "시작";;
  stop)
    echo "중지";;
  restart)
    echo "재시작";;
  *)
    echo "알 수 없는 파라미터";;
esac
exit 0
[sun@localhost ~]$ sh case1.sh stop
중지



조건문 - case~esac문(2)

[sun@localhost ~]$ vi case2.sh
#!/bin/sh
echo "쉘스크립트가 재밌어요? (yes/no)"
read answer
case $answer in
  yes | y | Y | Yes | YE)
    echo "거짓말쟁이";;
  [nN]*)
    echo "진실된 사람이군요";;
  *)
    echo "yes or no 입니다"
    exit 1;;
esac
exit 0
[sun@localhost ~]$ sh case2.sh st
쉘스크립트가 재밌어요? (yes/no)
No
진실된 사람이군요



AND / OR 관계 연산자

  • and는 && 사용
  • or는 || 사용
[sun@localhost ~]$ vi andor1.sh
#!/bin/sh
echo "보고싶은 파일명을 입력해보세요"
ls
read fname
if [ -f $fname ] && [ -s $fname ] ; then
  head -5 $fname
else
  echo "파일이 없거나 크기가 0입니다."
fi
exit 0
[sun@localhost ~]$ sh andor1.sh
보고싶은 파일명을 입력해보세요
andor1.sh  case2.sh  if2.sh  if4.sh   num1.sh   var1.sh
case1.sh   if1.sh    if3.sh  name.sh  para1.sh
case1.sh
#!/bin/sh
case "$1" in
  start)
    echo "시작";;
  stop)



반복문 - for문(1)

형식

for 변수 in 값1 값2 값3 ...
do
  반복할 문장
done

for i in 1 2 3 4 5 6 7 8 9 10

= for((i=1;i<=10;i++))

= for i in `seq 1 10`

[sun@localhost ~]$ vi for1.sh
#!/bin/sh
hap=0
for i in 1 2 3 4 5 6 7 8 9 10
#for((i=1;i<=10;i++))
#for i in `seq 1 10`
do
  hap=`expr $hap + $i`
done
echo "1~10까지의 합: "$hap
exit 0
[sun@localhost ~]$ sh for1.sh
1~10까지의 합: 55



반복문 - for문(2)

  • 현재 디렉터리에 있는 쉘 스크립트 파일(*.sh)의 파일명과 앞 3줄씩을 출력하는 프로그램
[sun@localhost ~]$ vi for2.sh
#!/bin/sh
for fname in $(ls *.sh)
do
  echo "--------$fname--------"
  head -3 $fname
done
exit 0
[sun@localhost ~]$ sh for2.sh
--------andor1.sh--------
#!/bin/sh
echo "보고싶은 파일명을 입력해보세요"
ls
--------case1.sh--------
#!/bin/sh
case "$1" in
  start)
--------case2.sh--------
#!/bin/sh
echo "쉘스크립트가 재밌어요? (yes/no)"
read answer
--------for1.sh--------
#!/bin/sh
hap=0
#for i in 1 2 3 4 5 6 7 8 9 10
--------for2.sh--------
#!/bin/sh
for fname in $(ls *.sh)
do
--------if1.sh--------
#!/bin/sh
if [ "woo" = "woo" ]
then
--------if2.sh--------
#!/bin/sh
if [ "woo" != "woo" ]
then
--------if3.sh--------
#!/bin/sh
if [ 100 -eq 200 ]
then
--------if4.sh--------
#!/bin/bash
fname=/home/sun/num1.sh
if [ -f $fname ]
--------name.sh--------
#!/bin/sh
echo "호스트명": $HOSTNAME
exit 0
--------num1.sh--------
#!/bin/sh
num1=100
num2=$num1+200
--------para1.sh--------
#!/bin/sh
echo "실행파일 이름은 <$0>"
echo "첫 번째 파라미터 <$1>"
--------var1.sh--------
#!/bin/sh
myvar="Hello Sun"
echo $myvar



반복문 - while문(1)

  • 조건문이 참인 동안 계속 반복
[sun@localhost ~]$ vi while1.sh
#!/bin/sh
while [ 1 ]
do
  echo "Sun"
done
exit 0
[sun@localhost ~]$ sh while1.sh
Sun
Sun
Sun
Sun
Sun
Sun
Sun
Sun
Sun
Sun
Sun
Sun
(무한반복... Ctrl+C로 끊어주기)

while은 조건에 [ 1 ] 또는 [ : ]가 오면 항상 참



반복문 - while문(2)

  • 1 ~ 10까지의 합계 출력(for1.sh와 동일한 결과)
[sun@localhost ~]$ vi while2.sh
#!/bin/sh
hap=0
i=1
while [ $i -le 10 ]
do
  hap=`expr $hap + $i`
  i=`expr $i + 1`
done
echo "1~10까지의 합: "$hap
exit 0
[sun@localhost ~]$ sh while2.sh
1~10까지의 합: 55

until문은 조건식이 참일때까지(거짓인 동안) 계속 반복

while [ $i -le 10 ] = until [ $i -gt 10 ]



반복문 - while문(3)

  • 비밀번호를 입력받고, 비밀번호가 맞을 때까지 계속 입력받는 스크립트
[sun@localhost ~]$ vi while3.sh
#!/bin/bash
echo "비밀번호를 입력하시오"
read mypass
while [ $mypass != "1234" ]
do
  echo "틀렸음. 재입력 요망"
  read mypass
done
echo "통과"
exit 0
[sun@localhost ~]$ sh while3.sh
비밀번호를 입력하시오
1
틀렸음. 재입력 요망
2
틀렸음. 재입력 요망
3
틀렸음. 재입력 요망
1234
통과



반복문 - until문

  • while문과 용도가 거의 같음

  • until문은 조건식이 참일때까지(=거짓일 동안) 계속 반복



break, continue, exit, return 문

  • break : 주로 반복문을 종료할 때 사용

  • continue : 반복문의 조건식으로 돌아가도록

  • exit : 해당 프로그램을 완전히 종료

  • return : 함수 안에서 사용될 수 있으며, 함수를 호출한 곳으로 돌아가도록

[sun@localhost ~]$ vi bce.sh
#!/bin/sh
echo "무한 반복 입력 시작(b: break, c: continue, e: exit)"
while [ 1 ] ; do
read input
case $input in
  b | B )
    break ;;
  c | C )
    echo "continue를 누르면 while의 조건으로 돌아감"
    continue ;;
  e | E )
    echo "exit를 누르면 프로그램(함수)를 완전히 종료"
    exit 1 ;;
esac;
done
echo "break를 누르면 while을 빠져나와 지금 이 문장이 출력됨"
exit 0
[sun@localhost ~]$ sh bce.sh
무한 반복 입력 시작(b: break, c: continue, e: exit)
a
b
break를 누르면 while을 빠져나와 지금 이 문장이 출력됨
[sun@localhost ~]$ sh bce.sh
무한 반복 입력 시작(b: break, c: continue, e: exit)
a
c
continue를 누르면 while의 조건으로 돌아감
e
exit를 누르면 프로그램(함수)를 완전히 종료



사용자 정의 함수

형식

함수이름() { # 함수를 정의
  내용들...
}
함수이름 # 함수 호출
[sun@localhost ~]$ vi func1.sh
#!/bin/sh
myFunction() {
  echo "myFunction 함수"
  return
}
echo "프로그램 시작"
myFunction
echo "프로그램 종료"
exit 0
[sun@localhost ~]$ sh func1.sh
프로그램 시작
myFunction 함수
프로그램 종료



함수의 파라미터 사용

형식

함수이름() { # 함수를 정의
  $1, $2 ... 등을 사용
}
함수이름 파라미터1 파라미터2 ... # 함수 호출
[sun@localhost ~]$ vi func2.sh
#!/bin/sh
hap () {
    echo `expr $1 + $2`
}
echo "10 + 20 실행"
hap 10 20
exit 0
[sun@localhost ~]$ sh func2.sh
10 + 20 실행
30



eval

  • 문자열을 명령문으로 인식하고 실행
[sun@localhost ~]$ vi eval.sh
#!/bin/sh
str="ls -a"
echo $str
eval $str
exit 0
[sun@localhost ~]$ sh eval.sh
ls -a
.              .bash_profile  case1.sh  for2.sh   if2.sh   num1.sh    while2.sh
..             .bashrc        case2.sh  func1.sh  if3.sh   para1.sh   while3.sh
.bash_history  andor1.sh      eval.sh   func2.sh  if4.sh   var1.sh
.bash_logout   bce.sh         for1.sh   if1.sh    name.sh  while1.sh



export

  • 외부 변수로 선언

  • 선언한 변수를 다른 프로그램에서도 사용할 수 있도록 해 줌

[sun@localhost ~]$ vi exp1.sh
#!/bin/sh
echo $var1
echo $var2
exit 0
[sun@localhost ~]$ vi exp2.sh
#!/bin/sh
var1="지역변수"
export var2="외부변수"
sh exp1.sh
exit 0
[sun@localhost ~]$ sh exp2.sh

외부변수
[sun@localhost ~]$ echo $var2



printf

  • C언어의 printf() 함수와 비슷하게 형식을 지정하여 출력
#!/bin/sh
var1=100.5
var2="재미있는건가 쉘스크립트"
printf "%5.2f \n\n \t %s \n" $var1 "$var2"
exit
[sun@localhost ~]$ sh printf.sh
100.50

         재미있는건가 쉘스크립트



set과 $(명령어)

  • 리눅스 명령어를 결과로 사용하기 위해서는 $(명령어) 형식을 사용

  • 결과를 파라미터로 사용하고자 할 때는 set과 함께 사용

[sun@localhost ~]$ vi set.sh
#!/bin/sh
echo "오늘 날짜는 $(date) 입니다."
set $(date)
echo "오늘은 $4 요일 입니다."
exit 0
[sun@localhost ~]$ sh set.sh
오늘 날짜는 2019. 10. 15. () 13:21:20 KST 입니다.
오늘은 () 요일 입니다.



shift

  • 파라미터 변수를 왼쪽으로 한 단계씩 아래로 쉬프트 시킴

  • 10개가 넘는 파라미터 변수에 접근할 때 사용

  • 단 $0 파라미터 변수는 변경되지 않음

  • 원하지 않는 결과의 소스

[sun@localhost ~]$ vi shift1.sh
#!/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
[sun@localhost ~]$ sh shift1.sh
AAA BBB CCC DDD EEE FFF GGG HHH III AAA0 AAA1
  • Shift 이용
[sun@localhost ~]$ vi shift2.sh
#!/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
[sun@localhost ~]$ sh shift2.sh
AAA BBB CCC DDD EEE FFF GGG HHH III JJJ KKK



매번 쉘 스크립트를 처음부터 만드는게 아니라, 기존에 사용했던 부분을 재활용해서 만들다보니

기초 문법을 점점 잊어갔었는데.. 되새김질 겸 정리