[리눅스] 11장 정리

Jingu_Jeon·2024년 6월 9일

Linux 스터디

목록 보기
6/8

학습목표

- 셸의 개념과 명령문 처리 방식을 이해한다.
- 셸 스크립트의 작성과 실행 방법을 익힌다.
- 다양한 문접을 활용하여 셸 스크립트를 작성한다.

셸의 개념

  • 리눅스의 셸(Shell)
    • 명령어와 프로그램을 실행할 때 사용하는 인터페이스
    • 역할
      • 사용자가 입력한 명령어를 해석하여 커널에 전달, 커널의 처리 결과를 사용자에게 전달
    • 셸은 Server(B)의 텍스트 모드처럼 명령어를 입력하는 환경과 비슷
    • 우분투(과거): bash쉘
    • 우분투(현재): dash쉘(기본쉘)
  • bash
    • 풍부한 기능과 다양한 문법 지원
    • 에일리어스 기능, 히스토리 기능
    • 연산 기능, job control 기능, 자동 이름 완성 기능
    • 프롬프트 제어 기능, 명령 편집 기능
    • 단점
      • 기능이 많아 속도가 느림
      • dash에 비해 실행 속도가 느림
  • dash
    • 장점
      • 슬림함(가볍고, 빠름)
      • 특히, 운영체제 시작 시 이전 버전의 데비안과 비교하여 더 빠른 셸 스크립트 실행
    • 사용자 상호작용 기능이 거의 없어서, bash 기반으로 작성한 스크립트가 dash에선 제대로 작동하지 않을 수 있음

셸의 명령문 처리 방법

  • 셸 명령문의 형식
    • (프롬프트) 명령 [옵션...][인자...]
  • 셸 명령문의 예
	# ls -l 
	# rm -rf /mydir
	# find . / -name "*.conf"

환경변수

  • 실행방법
    • 셸에서는 여러 가지 환경 변수 값을 불러올 수 있움
    • 설정된 환경 변수는 echo $환경변수 명령으로 확인 가능
    • 호스트 이름을 출력하려면 echo $HOSTNAME 명령을 실행
    • export 환경변수 = 값 명령을 실행하면, 환경 변수 값을 변경

셸 스크립트 작성

  • 작성 방법
    • 셸 스크립트도 일반적인 프로그래밍 언어와 비슷하게 변수, 반복문, 제어문 등을 사용
    • 별도로 컴파일하지 않고, 텍스트 파일 형태로 셸에서 바로 실행 가능
    • 셸 스크립트는 주로 vi, gedit으로 작성

셸 스크립트 실행

I. sh 명령으로 실행
ex)

  • sh 스크립트 파일 명령으로 실행하는 방법은 셸 스크립트 파일의 속성을 변경할 필요가 없다는 것이 장점

II. '실행 가능' 속성으로 변경한 후에 실행
ex)

  • 먼저 셸 스크립트 파일의 속성을 '실행 가능'으로 변경한 후에 ./스크립트파일 명령을 실행
  • chmod +x 파일명: 현재 파일의 속성에 '실행 가능' 속성을 추가하라는 명령

변수

  • 변수의 개요
    • 변수는 값을 계속 변경하여 저장하는 개념
    • 셸 스크립트에서는 변수를 사용하기 전에 미리 선언하지 않으며, 처음 변수에 값이 할당되면 자동으로 변수가 생성
    • 변수에 들어가는 모든 값은 문자열(String)로 취급되고, 숫자를 넣어도 동일하게 취급
    • 변수를 대입할 때 '=' 앞뒤에 공백이 없어야 함
      ex)
myVar = Hello -- ❗ = 앞뒤에 공백이 있음
myVar=Hello
myVar=Yes Sir -- ❗ 값의 공백은 " "로 묵어야 함
myVar="Yes Sir"
myVar=7+5 -- ❗ "7+5" 라는 문자열로 인식

변수의 입력과 출력

  • $가 포함된 글자를 출력하려면 ''로 묶거나 앞에 \를 넣어야 함
  • " "로 변수를 묶거나, 묶지 않아도 변수 값을 출력함
    ex)
var1.sh

#!/bin/sh
myvar="Hi Woo"
echo $myvar -- 'Hi Woo' 출력
echo "$myvar" -- 'Hi Woo' 출력
echo '$myvar' -- ''로 묶어서 '$myvar' 출력
echo \$myvar -- 앞에 \를 넣어서 '$myvar' 출력
echo 값 입력 : 
read myvar -- 변수 myvar에 키보드로 값(문자열) 입력
echo '$myvar' = $myvar -- '$myvar' -> $myvar 출력, $myvar -> myvar 변수 안의 문자열 출력
exit 0

결과

숫자 계산

  • 변수 값을 +, -, *, / 등으로 연산하려면 expr 키워드 사용
  • 단, 수식과 함께 키보드의 숫자 1 왼쪽에 있는 백쿼트(`)로 반드시 묶어야함
  • 수식에 괄호를 사용하려면 그 앞에 반드시 ()를 넣어야 함
  • +, -, / 와 달리 * 도 예외적으로 앞에 (*) 넣어야 함
numcalc.sh

#!/bin/sh
num1=100
num2=$num1+200
echo $num2   -- 문자열로 취급하여 100+200을 출력
num3=`expr $num1 + 200`   -- 숫자로 취급하여 계산하며 각 단어를 띄어쓰기 해야 함 
echo $num3   -- 300 출력
num4=`expr \( $num1 + 200 \) / 10 \* 2`   -- 괄호와 * 앞에는 \
echo $num4   -- 60 출력
exit 0

결과

파라미터(Parameter) 변수

  • 파리미터 변수는 $0, $1, $2... 형태(실행하는 명령의 각 부분을 변수로 지정한다는 의미)
    ex)
  • apt-get -y install gftp
  • 파라미터 변수
    • $0 : apt-get
    • $1 : -y
    • $2 : install
    • $3 : gftp
paravar.sh

#!/bin/sh
echo "실행파일 이름은 <$0>이다"   -- <$0> : paravar.sh
echo "첫번째 파라미터는 <$1>이고, 두번째 파라미터는 <$2>다"   -- <$1> : 1번, <$2> : 2번
echo "전체 파라미터는 <$*>다"   -- <$*> : 전체 파라미터 출력
exit 0

결과

if 문과 case 문

기본 if 문

  • [ 조건 ] 안의 각 단어 사이에 공백이 있어야 한다는 것을 주의해야 함
    ex)

    if1.sh
    
    #!/bin/sh
    if [ "cook" = "cook" ]   -- 각 단어 사이 띄어쓰기
    then 
     echo "참입니다"   -- "" 안의 문자열 출력
    fi
    exit 0

    결과

if~else 문

  • 참인 경우와 거짓인 경우를 구분하여 실행
    ex)
#!/bin/sh
if [ "cook" != "cook" ]
then
 echo "참입니다"
else
 echo "거짓입니다"
fi
exit 0

결과

조건문의 비교 연산자

  • 조건문에서는 문자열 비교와 산술 비교가 가능
  • 문자열 비교 연산자
  • 산술 비교 연산자

    ex)
#!/bin/sh
if [ 100 -eq 200 ]   -- -eq : 두 수식(또는 변수)이 같으면 참
then
 echo "100과 200은 같다."
else
 echo "100과 200은 다르다."
fi
exit 0

결과

파일 관련 조건

  • 파일 관련 조건

    ex)
if4.sh

#!/bin/sh
fname=/lib/systemd/system/cron.service   -- fname 변수에 cron 서버 실행 파일인 /lib/systemd/system/cron.service를 저장
if [ -f $fname ]   -- fname 변수에 저장된 /lib/systemd/system/cron.service 파일이 일반 파일이면 참이므로 5행을 실행하고, 그렇지 않으면 거짓이므로 7행을 실행함
then
 head -5 $fname   -- 일반 파일 이기때문에 fname에 들어 있는 파일의 앞부분 다섯 행을 출력
else
 echo "cron 서버가 설치되지 않았습니다."
fi
exit 0

결과

case~esac 문(1)

  • if 문은 참과 거짓, 두가지 경우에만 사용
  • 경우의 수가 셋 이상에서 중복된 if문 대신 사용 할 수 있는 case문
case1.sh

#!/bin/sh
case "$1" in   -- 첫 번째 파라미터 변수(명령 실행 시 추가한 값 : sh case1.sh stop($1) )인 $1 값에 따라서 3행, 5행, 7행, 9행으로 분기
 start)
  echo "시작~~";;   -- $1가 start면 실행. 끝에는 세미콜론 2개(;;)
 stop)
  echo "중지~~";;
 restart)
  echo "다시 시작~~";;
 *)   -- 정해진 경우의 수가 아닐경우 다음 구문을 실행
  echo "뭔지 모름~~";;
esac
exit 0

결과

case~esac 문(2)

#!/bin/sh
echo "공부가 재미있나요? (yes / no)"
read answer   -- answer 변수에 키보드로 값을 입력
case $answer in 
 yes | y | Y | Yes | YES)   -- 입력된 값이 yes, y, Y, YES 중 하나이면 6~7행을 실행함
  echo "다행입니다."   
  echo "더욱 열심히 하세요 ^^";;   -- 실행할 구문의 끝이므로 ;; 넣음
 [nN]*)   -- 앞에 n 또는 N이 들어가는 모든 단어를 인정
  echo "안타깝네요. ㅠㅠ";;
 *)
  echo "yes 아니면 no만 입력했어야죠"
  exit 1;;   -- 정상적인 종료가 아니므로 exit 1로 종료
esac
exit 0

결과

and, or 관계 연산자

  • and의 의미는 -a 또는 &&를, or은 -o 또는 ||를 사용
  • -a나 -o는 테스트문([]) 안에서 사용할 수 있는데, 이때 괄호 등의 특수문자 앞에는 ()를 넣어야 함
    ex)
andor.sh

#!/bin/sh
echo "보고 싶은 파일명을 입력하세요."
read fname
if [ -f $fname ] && [ -s $fname ]   -- 입력한 파일 이름이 일반 파일(-f)이고 크기가 0이 아니면(-s) 5행을 실행함.
then
 head -5 $fname
else
 echo "파일이 없거나, 크기가 0입니다."
fi
exit 0

반복문

for ~ in 문

  • 변수에 각각의 값을 넣은후, do 안에 있는 '반복할 문장'을 실행 -> 값의 개수만큼 반복 실행
for ~ in 문

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

ex)

forin1.sh

#i/bin/sh
hap=0   -- 합계를 누적할 hap 변수를 초기화
for i in 1 2 3 4 5 6 7 8 9 10   -- i 변수에 1~10을 넣어 5행을 열 번 실행함
do
 hap=`expr $hap + $i`   -- hap에 i 변수의 값을 누적
done
echo "1부터 10까지의 합: "$hap
exit 0

결과

ex)

forin2.sh

#!/bin/sh
for fname in $(ls *.sh)   -- faname 변수에 ls *.sh 명령의 실행 결과를 하나씩 넣어 4~5행을 실행
do
 echo "--------$fname--------"   -- 스크립트 파일 이름을 출력
 head -3 $fname   -- 스크립트 파일의 앞부분 3행을 출력
done
exit 0

결과

while 문

  • while 문은 조건식이 참인 동안 계속 반복 실행하는 것이 특징
while 문

#!/bin/sh
while [ 조건식 ]
do
 반복할 문장
done

ex)

while1.sh

#!/bin/sh
while [ 1 ]   -- 조건식 위치에 [ 1 ] 또는 [ : ]이 오면 항상 참이므로 4행을 무한 반복함
do
 echo "우분투 18.04 LTS"
done
exit 0

결과

ex)

while2.sh

#!/bin/sh
hap=0   -- 합계를 누적할 hap 변수를 초기화
i=0   -- 1부터 10까지 증가하는 i 변수를 선어
while [ $i -le 10 ]   -- i가 10보다 작거나 같으면 6~7행을 실행
do
 hap=`expr $hap + $i`   -- hap에 i 변수의 값을 누적
 i=`expr $i + 1`   -- i 변수의 값을 1씩 증가
done
echo "1부터 10 까지의 합 : $hap"
exit 0

결과

ex)

while3.sh

#!/bin/sh
echo "비밀번호를 입력하세요."
read mypass   -- mypass 변수에 키보드로부터 값을 입력 받음
while [ $mypass != "1234" ]   -- mypass 변수의 값이 '1234'가 아니면 6~7행을 실행
do
 echo "틀렸음. 다시 입력하세요."
 read mypass   -- 다시 mypass 변수에 값을 입력 받음
done
echo "통과~~"
exit 0

until 문

  • while 문과 용도가 거의 같음
  • 거짓인 동안 계속 반복 실행
  • 참이 될 때(until) 까지 실행
    ex) while2를 until로 표현
until2.sh

#!/bin/sh
hap=0   -- 합계를 누적할 hap 변수를 초기화
i=0   -- 1부터 10까지 증가하는 i 변수를 선어
until [ $i -gt 10 ]   -- i가 10보다 클 때 까지 실행
do
 hap=`expr $hap + $i`   -- hap에 i 변수의 값을 누적
 i=`expr $i + 1`   -- i 변수의 값을 1씩 증가
done
echo "1부터 10 까지의 합 : $hap"
exit 0

ex) while3를 until로 표현

until3.sh

#!/bin/sh
echo "비밀번호를 입력하세요."
read mypass   -- mypass 변수에 키보드로부터 값을 입력 받음
until [ $mypass = "1234" ]   -- mypass 변수의 값이 '1234'가 아니면 6~7행을 실행
do
 echo "틀렸음. 다시 입력하세요."
 read mypass   -- 다시 mypass 변수에 값을 입력 받음
done
echo "통과~~"
exit 0

break 문, continue 문, exit 문 return 문

  • break는 반복문을 종료할 때 주로 사용하며, continue는 반복문의 조건식으로 다시 돌아가게함
  • exit는 해당 프로그램을 완전히 종료
  • 함수안에서 사용할 수 있는 return은 함수를 호출한 곳으로 돌아가게 함
bce.sh

#!/bin/sh
echo "무한반복 입력을 시작합니다. (b: break, c: continue, e: exit)"
while [ 1 ] ; do   -- 무한 반복(while [ : ] 또는 while [ true ]와 동일)
 read input
 case $input in   -- 4행에서 입력한 값에 따라 분기
  b | B)   -- b 또는 B가 입력되면, 7행의 break를 실행(while문 종료, 16행 실행)
   break;;
  c | C)   -- continue를 실행(3행의 while문으로 돌아감)
   echo "continue를 누르면 while의 조건으로 돌아감"
   continue;;
  e | E)   -- 12 ~ 13행의 exit를 실행
   echo "exit를 누르면 프로그램(함수)을 완전히 종료함"
   exit 1;;
 esac;
done
echo "break를 누르면 while을 빠져나와 지금 이 문장이 출력됨."
exit 0

셸 스크립트 응용 기능

사용자 정의 함수

사용자 정의 함수

함수명 () {   -- 함수 정의
 내용
}
함수명   -- 함수 호출

ex)

func1.sh

#!/bin/sh
myFunction () {   -- 함수 정의
 echo "함수 안으로 들어 왔음"
 return
}
echo "프로그램을 시작합니다."
myFunction   -- 함수 호출
echo "프로그램을 종료합니다."
exit 0

결과

함수의 파라미터 사용

함수의 파라미터 사용

함수명 () {   -- 함수 정의
 $1, $2, ... 등을 사용
}
함수명 파라미터1 파라미터2 ...   -- 함수 호출

ex)

func2.sh

#!/bin/sh
hap () {
 echo `expr $1 + $2`   -- 넘겨받은 파라미터 $1과 $2fmf 더한 값을 출력
}
echo "10 더하기 20을 실행합니다"
hap 10 20   -- 넘겨줄 파라미터를 공백으로 분리하여 차례로 넣음
exit 0

결과

eval

  • 문자열을 명령문으로 인식하여 실행
    ex)
eval.sh

#!/bin/sh
str="ls -l eval.sh"
echo $str   -- str 변수의 값인 'ls -l eval.sh'라는 글자를 그대로 출력
eval $str   -- str 변수의 값인 'ls -l eval.sh'를 명령으로 인식하여 실행
exit 0

결과

export

  • 특정 변수를 전역 변수로 만들어 모든 셸에서 사용 가능함
    ex)
exp1.sh

#!/bin/sh
echo $var1   -- var1 변수 출력, var1은 지역변수 이므로 가져오지 못함.
echo $var2   -- var2 변수 출력, var2은 외부변수 이므로 exp2.sh에서 가져옴.
exit 0
exp2.sh

#!/bin/sh
var1="지역 변수"   -- var1은 지역변수
export var2="외부 변수"   -- export를 사용하여 var2를 외부변수로 사용
sh exp1.sh   -- exp1.sh 실행
exit 0

결과

printf

  • C 언어의 printf() 함수와 비슷하게 형식을 지정하여 출력
    ex)
printf.sh

#!/bin/sh
var1=200.5
var2="재미있는 비기너 우분투~~"   -- 공백이 있으므로 " "로 묶음
printf "%5.2f \n\n \t %s \n" $var1 "$var2"   -- %5.2f는 총 5자리, 소수점 아래 2자리까지 출력, \n 은 개행 문자, \t는 Tab 문자, %s는 문자열을 출력, $var2의 경우 값 중간에 공백이 있으므로 변수 이름을 " "로 묶음
exit

결과

set과 $(명령)

  • 리눅스 명령을 결과로 사용하려면 '$(명령)' 형식 이용
  • 결과를 파라미터로 사용하려면 set 명령 이용
    ex)
set.sh

#!/bin/sh
echo "오늘 날짜는 $(date) 입니다."   -- $(date)는 date 명령어를 실행한 결과
set $(date)   -- $(date)의 결과가 파라미터 변수 $1, $2, $3, ...에 저장($1 : 2020., $2 : 06., $3 : 27., $4 : (토), $5 : 16:31:17, $6 : KST
echo "오늘은 $4 요일 입니다."   -- 네 번째 파라미터($4)인 (토)을 출력
exit 0

결과

shift

  • 파라미터 변수를 왼쪽으로 한 단계씩 아래로 시프트(이동)
    ex)
shift.sh

#!/bin/sh
myfunc() {
 str=""   -- 결과를 누적할 str 변수를 초기화
 while [ "$1" != "" ]; do   -- $1 파라미터가 비어 있지 않는 동안(while) 반복실행
  str="$str $1"   -- str 변수에 $1을 추가
  shift   -- 전체 파라미터를 왼쪽으로 시프트
 done
 echo $str   -- while 문을 빠져나오면, 누적한 str 변수를 출력
}
myfunc AAA BBB CCC DDD EEE FFF GGG HHH JJJ KKK
exit 0

shift.sh
#!/bin/sh

profile
Back-end Developer를 목표로 하고 있는 전진구입니다.

0개의 댓글