1. 셸(Shell) 개요
셸은 명령어 해석기로, 사용자가 리눅스 커널에 요청을 보내 프로그램을 실행할 수 있는 인터페이스 역할을 시스템 수준에서 수행합니다. 사용자는 셸을 통해 프로세스를 시작하고, 일시 중지하며, 중지시키고 심지어 일부 프로그램을 작성할 수 있습니다.
리눅스에서 제공하는 셸 해석기 목록:
[사용자@호스트 ~]$ cat /etc/shells /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash /bin/tcsh /bin/csh
bash와 sh의 관계
[사용자@호스트 bin]$ ll | grep bash -rwxr-xr-x. 1 root root 941880 5월 11 2016 bash lrwxrwxrwx. 1 root root 4 5월 27 2017 sh -> bash
CentOS의 기본 해석기는 bash입니다
[사용자@호스트 bin]$ echo $SHELL /bin/bash
2. 셸 스크립트 입문
2.1 스크립트 형식
#!/bin/bash # 이렇게 시작 (해석기 지정)
2.2 첫 번째 셸 스크립트: 안녕하세요
【예시】:
[사용자@호스트 데이터]$ touch hello.sh [사용자@호스트 데이터]$ vi hello.sh hello.sh에 다음 내용 입력 #!/bin/bash echo "안녕하세요"
스크립트의 일반적인 실행 방법
방법 1: bash/sh + 상대/절대 경로 (스크립트에 +x 권한 부여 불필요)
방법 2: 스크립트 직접 실행 (실행 권한 필요)
주의:
- 방법 1: 본질적으로 bash 해석기가 스크립트를 실행해주므로, 스크립트 자체에 실행 권한이 필요 없습니다.
- 방법 2: 본질적으로 스크립트가 직접 실행되므로, 실행 권한이 필요합니다.
3. 변수
3.1 시스템 미리 정의된 변수
일반적인 시스템 변수
$HOME, $PWD, $SHELL, $USER, $PATH 등
【예시】
시스템 변수 값 확인: echo $HOME
현재 셸의 모든 변수 표시: set
3.2 사용자 정의 변수
기본 구문
- 변수 정의: 변수=값
- 변수 제거: unset 변수
- 정적 변수 선언: readonly 변수 (참고: unset 불가)
변수 정의 규칙
- 변수 이름은 Java와 동일한 규칙을 따릅니다.
- "=" 양쪽에 공백이 없어야 합니다.
- 기본적으로 문자열 타입입니다.
- 변수 값에 공백이 있을 경우, 큰따옴표나 작은따옴표를 사용합니다.
【예시】
(1) 변수 A 정의
[사용자@호스트 데이터]$ A=5 [사용자@호스트 데이터]$ echo $A 5
(2) 변수 A에 재할당
[사용자@호스트 데이터]$ A=8 [사용자@호스트 데이터]$ echo $A 8
(3) 변수 A 제거
[사용자@호스트 데이터]$ unset A [사용자@호스트 데이터]$ echo $A
(4) 정적 변수 B=2 선언 (unset 불가)
[사용자@호스트 데이터]$ readonly B=2 [사용자@호스트 데이터]$ echo $B 2 [사용자@호스트 데이터]$ B=9 -bash: B: readonly variable
(5) bash에서 변수는 기본적으로 문자열 타입이며, 직접 숫자 연산을 수행할 수 없음
[사용자@호스트102 ~]$ C=1+2 [사용자@호스트102 ~]$ echo $C 1+2
(6) 변수 값에 공백이 있는 경우, 큰따옴표나 작은따옴표로 감싸야 함
[사용자@호스트102 ~]$ D=I love banzhang -bash: world: command not found [사용자@호스트102 ~]$ D="I love banzhang" [사용자@호스트102 ~]$ echo $D I love banzhang
3.3 특수 변수
3.3.1 $n
기본 구문: $n
기능: n은 숫자입니다.
- $0: 스크립트 이름
- $1-$9: 첫 번째부터 아홉 번째까지의 매개변수
- n>10일 경우 중괄호 사용 필요 (예: ${10})
【예시】
[관리자@1025 데이터]# vim args.sh #!/bin/bash echo "$0 $1 $2" [관리자@1025 데이터]# bash args.sh 1 2 3 args.sh 1 2
3.3.2 $#
기본 구문: $#
기능: 모든 입력 매개변수의 개수를 가져옵니다. 주로 루프에 사용됩니다.
【예시】
[관리자@1025 데이터]# vim args.sh #!/bin/bash echo "$0 $1 $2" echo $# [관리자@1025 데이터]# bash args.sh 1 2 3 args.sh 1 2 3
3.3.3 $*, $@
기본 구문
- $*: 모든 매개변수를 하나의 문자열로 취급
- $@: 모든 매개변수를 각각 개별적으로 취급
【예시】
[관리자@1025 데이터]# vim args.sh #!/bin/bash echo "$0 $1 $2" echo $# echo $* echo $@ [관리자@1025 데이터]# bash args.sh 1 2 3 args.sh 1 2 3 1 2 3 1 2 3
3.3.4 $?
기본 구문: $?
기능: 마지막으로 실행된 명령어의 반환 상태입니다. 이전 명령어가 성공적으로 실행되면 0을 반환하고, 오류가 발생하면 0이 아닌 값을 반환합니다.
【예시】 greeting.sh 스크립트가 올바르게 실행되는지 확인
[관리자@1025 데이터]# bash greeting.sh 안녕하세요! [관리자@1025 데이터]# echo $? 0
4. 연산자
기본 구문
" $[연산식] "
【예시】 (2+3)*4 값 계산
[관리자@1025 데이터]# sum=$(((2+3)*4)) [관리자@1025 데이터]# echo sum sum [관리자@1025 데이터]# echo $sum 20 [관리자@1025 데이터]# sum=$[(2+3)*4] [관리자@1025 데이터]# echo $sum 20
5. 조건문
기본 구문
- (1) test condition
- (2) [ condition ] (주의: condition 앞뒤에 공백이 있어야 함)
주의: 조건이 비어있지 않으면 true로 간주됩니다. [ 문자열 ]은 true를 반환하지만, []는 false를 반환합니다.
일반적인 조건 판별
● 두 정수 비교
| 연산자 | 의미 |
|---|---|
| -lt | 보다 작음 (less than) |
| -gt | 보다 큼 (greater than) |
| -le | 보다 작거나 같음 (less equal) |
| -ge | 보다 크거나 같음 (greater equal) |
| -eq | 같음 (equal) |
| -ne | 같지 않음 (Not equal) |
| = | 문자열 비교 |
● 파일 권한 기준 판별
| 연산자 | 의미 |
|---|---|
| -r | 읽기 권한 (read) |
| -w | 쓰기 권한 (write) |
| -x | 실행 권한 (execute) |
● 파일 타입 기준 판별
| 연산자 | 의미 |
|---|---|
| -f | 파일이 존재하고 일반 파일인 경우 (file) |
| -e | 파일이 존재하는 경우 (existence) |
| -d | 존재하고 디렉토리인 경우 (directory) |
【예시】
(1) 23이 22보다 크거나 같은지 확인
[관리자@1025 데이터]# [ 23 -ge 22 ] [관리자@1025 데이터]# echo $? 0
(2) greeting.sh에 쓰기 권한이 있는지 확인
[관리자@1025 데이터]# ll 총량 8 -rw-r--r--. 1 root root 32 12월 8 07:32 greeting.sh -rw-r--r--. 1 root root 52 12월 8 07:27 args.sh [관리자@1025 데이터]# [ -w greeting.sh ] [관리자@1025 데이터]# echo $? 0
(3) /opt/datas 디렉토리에 파일이 존재하는지 확인
[관리자@1025 opt]# [ -e /opt/datas ] [관리자@1025 opt]# echo $? 0
(4) 다중 조건 판별 (&&는 이전 명령어가 성공했을 때 다음 명령어를 실행하고, ||는 이전 명령어가 실패했을 때 다음 명령어를 실행합니다)
[관리자@1025 데이터]# [ condition ] && echo true || echo false
6. 제어 흐름 (중요)
6.1 if 문
기본 구문
| if [ 조건식 ]; then 프로그램 fi |
| 또는 |
| if [ 조건식 ] then 프로그램 elif [ 조건식 ] then 프로그램 else 프로그램 fi |
주의:
- [ 조건식 ]에서 대괄호와 조건식 사이에 공백이 있어야 합니다.
- if 뒤에 공백이 있어야 합니다.
【예시】
숫자 하나를 입력받아, 1이면 "첫 번째 선택"을 출력하고, 2이면 "두 번째 선택"을 출력하며, 3이면 "세 번째 선택"을 출력하고, 그 외에는 아무것도 출력하지 않습니다.
[관리자@1025 데이터]# vim check.sh
[관리자@1025 데이터]# bash check.sh 3
세 번째 선택
[관리자@1025 데이터]# bash check.sh 1
첫 번째 선택
[관리자@1025 데이터]# bash check.sh 2
두 번째 선택
#!/bin/bash
if [ $1 -eq "1" ]
then
echo "첫 번째 선택"
elif [ $1 -eq "2" ]
then
echo "두 번째 선택"
elif [ $1 -eq "3" ]
then
echo "세 번째 선택"
fi
6.2 case 문
기본 구문
| case $변수명 in "값1") 변수값이 값1과 같으면 프로그램1 실행 ;; "값2") 변수값이 값2와 같으면 프로그램2 실행 ;; … 다른 분생들 … *) 변수값이 위의 값들과 다르면 이 프로그램 실행 ;; esac |
주의사항:
- case 행 끝에는 반드시 단어 "in"이 있어야 하고, 각 패턴 일치는 오른쪽 괄호 ")"로 끝나야 합니다.
- 이중 세미콜론 ";;"은 명령어 시퀀스의 끝을 의미하며, Java의 break와 같습니다.
- 마지막의 "* )"는 기본 패턴을 의미하며, Java의 default와 같습니다.
【예시】
숫자 하나를 입력받아, 1이면 "첫 번째 선택"을 출력하고, 2이면 "두 번째 선택"을 출력하며, 3이면 "세 번째 선택"을 출력하고, 그 외에는 "기본값 출력"을 출력합니다.
[관리자@1025 데이터]# vim case.sh
[관리자@1025 데이터]# bash case.sh 1
첫 번째 선택
[관리자@1025 데이터]# bash case.sh 2
두 번째 선택
[관리자@1025 데이터]# bash case.sh 3
세 번째 선택
[관리자@1025 데이터]# bash case.sh 7
기본값 출력
#!/bin/bash
case $1 in
"1")
echo "첫 번째 선택"
;;
"2")
echo "두 번째 선택"
;;
"3")
echo "세 번째 선택"
;;
*)
echo "기본값 출력"
;;
esac
6.3 for 반복문
기본 구문 1
| for (( 초기값; 반복 조건; 변수 변경 )) do 프로그램 done |
【예시】 1부터 100까지의 합 계산
[관리자@1025 데이터]# vim sum1.sh
[관리자@1025 데이터]# bash sum1.sh
5050
#!/bin/bash
sum=0
for((i=0;i<=100;i++))
do
sum=$[$sum+$i]
done
echo $sum
기본 구문 2
| for 변수 in 값1 값2 값3… do 프로그램 done |
【예시】
(1) 모든 입력 매개변수 출력
[관리자@1025 데이터]# print.sh
[관리자@1025 데이터]# bash print.sh kim lee park
kim님 안녕하세요
lee님 안녕하세요
park님 안녕하세요
#!/bin/bash
for i in $*
do
echo "$i님 안녕하세요"
done
(2) $*와 $@의 비교
$*와 $@는 함수나 스크립트에 전달된 모든 매개변수를 나타냅니다.
【예시 1】 $*, $@에 ""를 사용하지 않을 경우, $1 $2 …$n 형식으로 모든 매개변수 출력
[관리자@1025 opt]# compare.sh
[관리자@1025 opt]# bash compare.sh kim lee park
kim님 안녕하세요
lee님 안녕하세요
park님 안녕하세요
---------------------
kim lee park님 안녕하세요
#!/bin/bash
for i in $*
do
echo "$i님 안녕하세요"
done
echo "---------------------"
for j in $@
do
echo "$j님 안녕하세요"
done
【예시 2】 $*, $@에 ""를 사용할 경우, "$*"는 "$1 $2 …$n" 형식으로 전체 출력하고, "$@"는 "$1", "$2", …, "$n" 형식으로 분리하여 출력합니다.
[관리자@1025 opt]# compare.sh
[관리자@1025 opt]# bash compare.sh kim lee park
kim lee park님 안녕하세요
---------------------
kim님 안녕하세요
lee님 안녕하세요
park님 안녕하세요
#!/bin/bash
for i in "$*"
#$*의 모든 매개변수를 하나의 문자열로 취급하므로 이 for 루프는 한 번만 실행됩니다
do
echo "$i님 안녕하세요"
done
echo "---------------------"
for j in "$@"
#$@의 각 매개변수를 별개로 취급하므로 "$@"에 몇 개의 매개변수가 있으면 몇 번이나 루프가 실행됩니다
do
echo "$j님 안녕하세요"
done
6.4 while 반복문
기본 구문
| while [ 조건식 ] do 프로그램 done |
【예시】
[관리자@1025 데이터]# while_sum.sh
[관리자@1025 데이터]# bash while_sum.sh
5050
#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
s=$[$s+$i]
i=$[$i+1]
done
echo $s
7. read로 콘솔 입력 읽기
기본 구문
| read(옵션)(매개변수) 옵션: -p: 값 읽기 시 지시어 지정 -t: 값 읽기 대기 시간(초) 지정 매개변수 변수: 값 읽기 위한 변수명 지정 |
【예시】 7초 내에 콘솔에서 이름 입력받기
[관리자@1025 데이터]# input.sh [관리자@1025 데이터]# bash input.sh 7초 안에 이름을 입력하세요: 홍길동 홍길동 #!/bin/bash read -t 7 -p "7초 안에 이름을 입력하세요: " NAME echo $NAME
8. 함수
8.1 시스템 함수
8.1.1 basename
기본 구문
basename [문자열/경로명] [접미사]
기능 설명: basename 명령어는 모든 접두사를 포함 마지막 '/' 문자까지 제거한 후 문자열을 표시합니다.
옵션:
접미사: 접미사가 지정된 경우, 경로명이나 문자열에서 접미사를 제거합니다.
【예시】 /opt/data.txt 경로의 파일명 추출
8.1.2 dirname
기본 구문
dirname 파일 절대 경로
기능 설명: 주어진 절대 경로 파일명에서 파일명(디렉토리가 아닌 부분)을 제거하고, 남은 경로(디렉토리 부분)를 반환합니다.
【예시】 data.txt 파일의 경로 가져오기
8.2 사용자 정의 함수
기본 구문
| [ function ] 함수명[()] { 동작; [return 정수;] } 함수명 |
주의:
- 먼저 함수를 선언한 후 호출합니다.
- 셸 스크립트는 한 줄씩 실행됩니다. 다른 언어처럼 먼저 컴파일하지 않습니다.
- 함수 반환값은 $? 시스템 변수를 통해 얻을 수 있습니다. 명시적으로 return으로 반환할 수도 있고, 그렇지 않으면 마지막 명령어 실행 결과를 반환값으로 사용합니다. return 뒤에는 숫자 n(0-255)이 옵니다.
【예시】
[관리자@1025 opt]# calc.sh
[관리자@1025 opt]# bash calc.sh
첫 번째 숫자를 입력하세요: 3
두 번째 숫자를 입력하세요: 5
8
function add()
{
result=0
result=$[ $1 + $2 ]
echo "$result"
}
read -p "첫 번째 숫자를 입력하세요: " num1;
read -p "두 번째 숫자를 입력하세요: " num2;
add $num1 $num2;