리눅스 서버를 자동화하여 관리하기 위한 쉘 스크립트(Shell Script) 심화 강좌를 정리합니다.
출처 : inflearn
1. 쉘 스크립트란 무엇입니까?
- 쉘(Shell)은 명령 인터프리터(Command interpreter)입니다.
- 사용자가 운영체제에 대화식(interactively)으로 명령을 내리거나,
명령을 일괄(batch)적으로 실행 할 수 있는 기능을 제공하는 응용프로그램입니다. - 쉘은 사용자가 시스템과 대화 할 수 있는 방법이라고 생각하십시오.
- Kernel
- Core of the OS
- Allocates time and memory to programs
- Shell
- Outer layer of OS
- Interacts with user
- Sends requests to kernel
- 인기있는 쉘의 종류
- sh : Thompson Shell(1971)
- sh : Bourne Shell(1977)
- csh : C Shell(1979)
- tcsh : Tabbed C Shell(1979)
- ksh : Korn Shell(1982)
- bash : Bourne-Again Shell(1987)
- zsh : Z Shell(1990)
- dash : Dash Shell(2002)
2. 스크립트 작성방법
linux:/home/shkim/shell_cmd$ vi helloworld.sh
#!/bin/bash # 쉬뱅, 해쉬뱅 이라고 부른다.
echo hello world
#!/bin/env bash # 이렇게 해도 정상 동작 함.
echo hello world
linux:/home/shkim/shell_cmd$ ps
PID TTY TIME CMD
6727 pts/0 00:00:00 bash #bash는 항상 background로 실행되고 있음.
6802 pts/0 00:00:00 ps
3. DOS 스타일의 줄끝
linux:/home/shkim/shell_cmd$ echo -e 'hello\n\n\n'
hello
linux:/home/shkim/shell_cmd$
- 리눅스에서는 줄바꿈시 10 0A :
LF
Line Feed 만 사용되지만, - 윈도우에서는 줄바꿈시 10 0A :
LF
, 13 0DCR
Carriage Return LF,CR 2개가 사용됨.아래참고 - 파일 수정시 리눅스 공식 VIM 사용을 추천함.
linux:/home/shkim/shell_cmd$ hexdump -C hello.txt
00000000 68 65 6c 6c 6f 0a |hello.|
00000006
linux:/home/shkim/shell_cmd$ hexdump -C hello_ms.txt
00000000 68 65 6c 6c 6f 0a 0d |hello..|
00000007
linux:/home/shkim/shell_cmd$
4. 스크립트의 실행방법 4가지
linux:/home/shkim/shell_cmd$ ./helloworld.sh
hello world
linux:/home/shkim/shell_cmd$ bash helloworld.sh
hello world
linux:/home/shkim/shell_cmd$ source helloworld.sh
hello world
linux:/home/shkim/shell_cmd$ . helloworld.sh
hello world
5. 특수문자 종류 미리보기
-
- 공백(White Space) :
- 탭(tab), 줄 바꿈(newline), 세로 탭, 양식 공급(form feed),
캘리지 리턴(Carriage Return) 또는 공백(White Space)입니다.Bash는 공백을 사용하여 단어의 시작과 끝을 결정합니다. 사용자가 명령어를 입력할 시,
첫번째 단어는 명령이름이며, 추가단어는 해당명령에 대한 인수가 됩니다.
-
- 확장(Expansion) : ${}, $(), $(())
- 다양한 유형의 확장(Extenstion)을 도입합니다.
- parameter expansion (파라미터 확장) : $var or ${var}
- command substitution (명령 대체) : $(command)
- arithmetic expansion (산술 확장) : $((expression))
-
- 큰 따옴표(Double Quotes) : “ “
- 그 안의 텍스트가 여러 단어나 인수로 분리되지 않도록 보호합니다.
큰 따옴표 내의 문자들을 대체(Substitution)하는 것이 가능합니다.
\
(백슬러시),$
(달러),``(백틱)를 제외한 대부분의 다른 특수 문자의 의미는 억제됩니다.(즉 일반문자로 해석됩니다.)
-
- 작은 따옴표(Single Quote) : ‘ ‘
- 문자 그대로의 의미를 갖도록 텍스트를 보호하십시오.
_모든 특수문자의 해석이 방지됩니다.(인용부호 안의 문자열 내용을 Bash가 해석하지 않습니다.)
특수문자가 그대로 전달되고 여러 단어가 분할되지 않습니다.
linux:/home/shkim/shell_cmd$ echo "사용법: `basename $HOME` filename"
사용법: shkim filename
linux:/home/shkim/shell_cmd$ echo '사용법: `basename $HOME` filename'
사용법: `basename $HOME` filename
-
- 탈출(Escape) : \
- 다음 문자가 특수문자로 해석되는 것을 방지합니다.
큰 따옴표 안에서 작동하며 작은 따옴표로는 일반적으로 무시됩니다.
linux:/home/shkim/shell_cmd$ echo "사용법:\`basename \$HOME\` filename"
사용법:`basename $HOME` filename
-
- 주석(Comment) : #
- ’#’ 문자의 도입은 그 행의 끝까지 모두 주석으로 처리됩니다.
코멘트는 설명의 주석이며 쉘에 의해 처리되지 않습니다.
-
- 테스트(Test) : [[ ]]
- 조건부 표현식이 “true”인지 “false”인지를 결정하기 위한 조건식의 평가
테스트는 Bash에서 여러 조건을 평가하는데 사용됩니다.
-
- 부정하다(Negate) : !
- 테스트나 종료 상태를 무효화하거나 되돌리기 위해 사용됩니다.
-
- 방향재지정(Redirection) : > <
- 명령의 출력또는 입력을 재 지정합니다.
linux:/home/shkim$ rm dir1 2>/dev/null # 에러 메세지는 무시
-
- 파이프(PIPE) : |
- 초기 명령의 출력을 2차 명령의 입력으로 재 지정합니다.
linux:/home/shkim$ echo "Hello World" | grep -o World
World
linux:/home/shkim$ echo "60+1" | bc
61
-
- 명령 분리자(Command Separator) : ;
- 같은 줄에 있는 여러 명령을 구분하는데 사용됩니다.
linux:/home/shkim/shell_cmd$ sum=0;while read num ; do sum=$(($sum + $num)); done < nums.txt; echo $sum
5050
-
- 인라인 그룹(Inline Group) : { }
- 중괄호 안의 명령은 마치 하나의 명령처럼 취급됩니다.
_Bash구문이 하나의 명령만을 필요로 하고, 함수의 사용은 피하고 싶을 때, 이것을 사용하는 것이 편리합니다.
linux:/home/shkim$ { local v1; v1=123; }
-bash: local: can only be used in a function
-
- 서브 쉘 그룹(SubShell Group)
- 위와 비슷하지만 내부 명령이 서브 쉘에서 실행되는 경우
명령이 부작용을 일으키는 경우 샌드박스처럼 많이 사용됩니다.(변수 변경하기 같은 경우)
현재의 쉘에는 영향을 주지 않습니다.
linux:/home/shkim/shell_cmd$ u2dos() (set -f; IFS=''; printf '%s\r\n' $(cat "$1"))
linux:/home/shkim/shell_cmd$ u2dos helloworld.sh
#!/usr/bin/env bash
echo hello world
-
- 산술 표현식(Arithmetic Expression) : (( ))
- 산술 표현식에서 +, -, *, / 같은 문자는 계산에 사용되는 수학 연산자 입니다.
그것들은 다음과 같은 변수 할당에 사용할 수 있습니다.((a=1+4), 테스트에도 사용합니다 if((a<b))
-
- 산술 확장(Arithmetic Expansion) : $(( ))
- 위와 유사하지만 표현식은 산술 계산 결과로 대체됩니다.
linux:/home/shkim/shell_cmd$ echo "The average is $(( (a+b)/2))"
The average is 0
-
- 홈 디렉토리(Home Directory) : ~
- ~(tild)는 홈 디렉토리를 나타냅니다.
그 다음에 \ 이 올때 ~는 현재 사용자의 홈 디렉토리를 나타냅니다.
또는 사용자 이름을 지정해야 합니다.
linux:/etc$ ~/shell_cmd/helloworld.sh
hello world
6. 쉘 변수
linux:/home/shkim$ animal=tiger # 변수 대입, 공백이 있으면 안됨.
linux:/home/shkim$ color=white
linux:/home/shkim$ echo "tiger's color is $color"
7. 파라미터 대체와 인용부호
linux:/home/shkim/mydir$ touch "The old man and the sea.mp3"
linux:/home/shkim/mydir$ echo $book
The old man and the sea.mp3
linux:/home/shkim/mydir$ ls
The old man and the sea.mp3
linux:/home/shkim/mydir$ rm $book
rm: cannot remove ‘The’: No such file or directory
rm: cannot remove ‘old’: No such file or directory
rm: cannot remove ‘man’: No such file or directory
rm: cannot remove ‘and’: No such file or directory
rm: cannot remove ‘the’: No such file or directory
rm: cannot remove ‘sea.mp3’: No such file or directory
linux:/home/shkim/mydir$ rm "$book"
linux:/home/shkim/mydir$ ls
linux:/home/shkim/mydir$ animal=Tiger; color=Red
linux:/home/shkim/mydir$ echo "$animals $colors"
linux:/home/shkim/mydir$ echo ${animal}s vs. ${color}s
Tigers vs. Reds
linux:/home/shkim/mydir$ echo "${animal}s vs. ${color}s" #인용부호로 확실하게 하는게 더 좋다.
Tigers vs. Reds
8. 특수 매개 변수
linux:/home/shkim$ vi whereis.sh
#!/bin/bash
DIRECTORY=`dirname $0`
echo $DIRECTORY
linux:/home/shkim$ ./where.sh
linux:/home/shkim$ /home/shkim/where.sh
/home/shkim
linux:/home/shkim$ vi whois.sh
#!/bin/bash
name=$1
email=$2
all=$*
echo "your name is $name"
echo "your email is $email"
echo "* is $all"
linux:/home/shkim$ ./whois.sh
your name is
your email is
* is
linux:/home/shkim$ ./whois.sh shkim shkim@gmail.com #전달인자가 있어야 함.
your name is shkim
your email is shkim@gmail.com
* is shkim shkim@gmail.com
특수매개변수
Name | Usage | Description |
---|---|---|
0 | $0 | 스크립트의 이름 또는 경로를 포함합니다. |
1 2 etc | $1 etc | 위치 매개 변수에는 현재 스크립트 또는 함수에 전달된 인수가 포함됩니다. |
* | ”$*” | 모든 위치 매개 변수의 모든 단어로 확장됩니다. 큰 따옴표를 붙이면, IFS 변수의 첫번째 문자로 분리 된 모든 문자열을 포함하는 단일 문자열로 확장됩니다. |
@ | $@ | 모든 위치 매개변수의 모든 단어로 확장됩니다. 큰 따옴표로 묶어서 개별 단어로 모두 목록으로 확장합니다. |
# | $# | 위치 매개 변수의 수로 확장 됩니다. |
? | $? | 가장 최근에 완료한 포 그라운드 명령의 종료 코드로 확장합니다. |
$ | $$ | 현재 쉘의 PID(프로세스ID)으로 확장됩니다. |
! | $! | 백그라운드에서 가장 최근에 실행된 명령의 PID로 확장합니다. |
_ | $_ | 실행된 마지막 명령의 마지막 인수로 확장합니다. |
linux:/home/shkim$ vi whois.sh
#!/bin/bash
name=$1
email=$2
all=$*
if [ $# -eq 0 ] # 전달인자의 개수가 0 이면~
then
echo "No arguments supplied"
fi
echo "your name is $name"
echo "your email is $email"
echo "* is $all"
linux:/home/shkim$ ./whois.sh
No arguments supplied
your name is
your email is
* is
9. 환경변수
linux:/home/shkim$ echo "USER ID : $UID"
USER ID : 1001
linux:/home/shkim$ vi euid.sh
#!/bin/bash
if [ "$EUID" -ne 0 ]; then # Effected User ID
echo "run as root"
exit
fi
echo hello
linux:/home/shkim$ chmod +x euid.sh
linux:/home/shkim$ ./euid.sh
run as root
linux:/home/shkim$ sudo ./euid.sh
hello
linux:/home/shkim$ echo "$RANDOM"
5502
linux:/home/shkim$ echo "$RANDOM"
11364
linux:/home/shkim$ echo "$RANDOM"
2396
10. declare
linux:/home/shkim$ declare -a alnum=(a1 b1 c1 d1 e1 f1) # -a 배열 옵션
linux:/home/shkim$ echo ${alnum[2]}
c1
linux:/home/shkim$ declare -i inum=78 #정수형 변수
linux:/home/shkim$ inum=inum+1
linux:/home/shkim$ echo $inum
79
linux:/home/shkim$ num=78 # 7과 8이라는 문자로 인식됨.
linux:/home/shkim$ num=num+1
linux:/home/shkim$ echo $num
num+1
linux:/home/shkim$ declare -r rPi=3.14 # -r 읽기전용 번수
linux:/home/shkim$ rPi=312 # 초기화 불가함.
-bash: rPi: readonly variable
linux:/home/shkim$ declare -x xpath="${HOME}/Desktop/mydir" # 변수를 export 하기
linux:/home/shkim$ export XPATH="${HOME}/Desktop/mydir" # 위와 동일함.
11. 매개변수 확장(PE)
linux:/home/shkim$ testString="That that is is that that is not is not"
linux:/home/shkim$ echo ${#testString} # 문자열의 수를 셀 때
39
linux:/home/shkim$ echo ${testString:0} # 원하는 문자열의 시작점을 지정할 수 있다.
That that is is that that is not is not
linux:/home/shkim$ echo ${testString:1}
hat that is is that that is not is not
linux:/home/shkim$ echo ${testString:3}
t that is is that that is not is not
linux:/home/shkim$ echo ${testString:3:3} #4번째 문자열 부터 3 chracter
t t
linux:/home/shkim$ echo ${testString#T*is} # 대문자 T로 시작하고 is로 끝나는 문자열 제거
is that that is not is not
linux:/home/shkim$ echo ${testString##T*is} # 대문자 T로 시작하고 is로 큰 집합 제거
not
linux:/home/shkim$ echo ${testString%is*not} # 문장 뒤부터 검색해서 소문자 is로 시작해서 not 으로 끝나는 문자열제거
That that is is that that is not
linux:/home/shkim$ echo ${testString%%is*not} # 문장 뒤부터 검색해서 소문자 is로 시작해서 not 으로 끝나는 큰 집합의 문자열제거
That that
linux:/home/shkim$ echo ${testString//that} # 해당 단어와 일치하는 문자 제거
That is is is not is not
linux:/home/shkim$ echo ${testString/that/this} # 매칭이 일어난 1개의 단어와 치환
That this is is that that is not is not
linux:/home/shkim$ echo ${testString/[tT]hat/this} # 대소문자 상관없이 that 단어를 this로 치환 / 처음매치된 1개 단어만 치환됨.
this that is is that that is not is not
linux:/home/shkim$ echo ${testString//[tT]hat/this} # 대소문자 상관없이 that 단어 --> this로 모두 치환
this this is is this this is not is not
linux:/home/shkim$ echo ${testString/#That/this}
this that is is that that is not is not
linux:/home/shkim$ echo ${testString/%not/NO} # 마지막 문자에서 매칭 후 치환
That that is is that that is not is NO
12. glob 패턴
linux:/home/shkim$ cd /
linux:/$ echo *
bin boot dev etc home lib lib64 local media mnt opt proc root run sbin srv sys tmp usr var
linux:/$ echo ??? # 3글자의 파일,디렉토리 출력
bin dev etc lib mnt opt run srv sys tmp usr var
linux:/$ echo ???? # 4글자 파일,디렉토 출력
boot home proc root sbin
linux:/$ echo b?? # b로시작하는 3글자 출력
bin
linux:/$ echo [abcd]* # a,b,c,d 로 시작하는 모든 파일이나 디렉토리 출력
bin boot dev
linux:/$ echo [a-d]* # a,b,c,d 로 시작하는 모든 파일이나 디렉토리 출력
bin boot dev
13. 명령어(tr)
- tr : 지정한 문자를 바꾸어주거나 삭제하기 위한 명령 줄 유틸리티.
- «< : 히어스트링(Here String)
- [::] : POSIX chracter sets
linux:/$ tr abcdefghijklmnopqrstuvwxyz ZABCDEFGHIJKLMNOPQRSTUVWXY <<< "Hello World"
HDKKN WNQKC # 해당 문자열에 해당하는 문자는 새로운 패턴으로 치환되어 출력됨.
linux:/$ tr [:lower:] [:upper:] <<< "Hello World"
HELLO WORLD # 모든 문자열을 대문자로
linux:/$ tr [:space:] '\t' <<< "Hello World" # 공백을 tab 으로 치환
Hello World linux:/$
linux:/$ tr -s [:space:] <<< "Hello World" #-s : Squeeze 반복되는 글자를 1글자로 축약
Hello World
linux:/$ tr -d [:space:] <<< "Hello World" # 모든 공백문자 제거
HelloWorld
linux:/$ tr -cd [:space:] <<< "Hello World" # -c complement 지정한 글자를 제외한 다른글자를 뜻함.
linux:/$
14. 명령어(cut)
linux:/home/shkim/shell_cmd$ cat fruits.txt
grapes
orange
tomato
strawberry
apple
linux:/home/shkim/shell_cmd$ cut -c2 fruits.txt # 각행의 2번째 글자 출력
r
r
o
t
p
linux:/home/shkim/shell_cmd$ cut -c1-3 fruits.txt #각행 1~3번째 글자 출력
gra
ora
tom
str
app
linux:/home/shkim/shell_cmd$ cut -c3- fruits.txt # 각행 3~마지막 글자 출력
apes
ange
mato
rawberry
ple
linux:/home/shkim/shell_cmd$ cut -c1-5 fruits.txt
grape
orang
tomat
straw
apple
linux:/home/shkim/shell_cmd$ cut -d':' -f1 /etc/passwd # 첫번째 필드 출력
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
games
ftp
nobody
systemd-network
dbus
rpc
libstoragemgmt
sshd
rpcuser
nfsnobody
ec2-instance-connect
postfix
chrony
rngd
tcpdump
shkim
linux:/home/shkim/shell_cmd$ cut -d':' -f1,6 /etc/passwd #첫번째,여섯번째 필드 출력
root:/root
bin:/bin
daemon:/sbin
adm:/var/adm
lp:/var/spool/lpd
sync:/sbin
shutdown:/sbin
halt:/sbin
mail:/var/spool/mail
operator:/root
games:/usr/games
ftp:/var/ftp
nobody:/
systemd-network:/
dbus:/
rpc:/var/lib/rpcbind
libstoragemgmt:/var/run/lsm
sshd:/var/empty/sshd
rpcuser:/var/lib/nfs
nfsnobody:/var/lib/nfs
ec2-instance-connect:/home/ec2-instance-connect
postfix:/var/spool/postfix
chrony:/var/lib/chrony
rngd:/var/lib/rngd
tcpdump:/
linux:/home/shkim$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 9001
inet 172.16.1.166 netmask 255.255.255.0 broadcast 172.16.1.255
inet6 fe80::9b:f8ff:fe5e:e306 prefixlen 64 scopeid 0x20<link>
ether 02:9b:f8:5e:e3:06 txqueuelen 1000 (Ethernet)
RX packets 276655 bytes 140617913 (134.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 200482 bytes 16342086 (15.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
linux:/home/shkim$ ifconfig eth0 | grep 'inet' | cut -d: -f2 | awk '{print $2}'
172.16.1.166
15. 확장 glob
- 확장 glob는 기본적으로 disable 되어있어 사용시 enable 하고 사용해야 합니다.
linux:/home/shkim/shell_cmd/images$ ls
Balloon.jpg glob.gif settings_up.png smaller.tiff
Candy.jpg settings_down.png shadingimage.tiff
linux:/home/shkim/shell_cmd/images$ echo *jpg *bmp
Balloon.jpg Candy.jpg *bmp
linux:/home/shkim/shell_cmd/images$ shopt -s extglob # 확장 glob 사용
linux:/home/shkim/shell_cmd/images$ echo !(*jpg|*bmp) # jpg,bmp 를 제외한 파일 출력
glob.gif settings_down.png settings_up.png shadingimage.tiff smaller.tiff
linux:/home/shkim/shell_cmd/images$ echo @(*jpg|*bmp) # @는 or의 기능
Balloon.jpg Candy.jpg
-
- 확장된 글로브(Extended Globs)
- 이들은 globs에서 사용 할 수 있는 메타 문자입니다.
Name | Description |
---|---|
?(list) | 주어진 패턴의 0번 또는 1번 일치 시킵니다. |
*(list) | 주어진 패턴의 0회 이상 일치 |
+(list) | 주어진 패턴의 하나 이상의 일치와 일치합니다. |
@(list) | 주어진 패턴 중 하나와 일치합니다. |
!(list) | 주어진 패턴을 제외한 모든 것을 일치시킵니다. |
16. 쉘 스크립트 문법 검사 도구
- 쉘 스크립트 정적 분석 도구로 유용한 웹사이트
- 스크립트 오류검사 사이트 : https://shellcheck.net
17. 컬러(color)텍스트
linux:/home/shkim$ echo -e '\033[34;40mNew Color Prompt\033[0m'
New Color Prompt # 실제로는 파란색으로 나옴
linux:/home/shkim$ echo -e '\033[37;41mNew Color Prompt\033[0m'
New Color Prompt
linux:/home/shkim$ echo -e '\033[1;37;41mNew Color Prompt\033[0m'
New Color Prompt
- 사용방법
'\033[1;37;44m COLOR \033[0m'
#\033:이스케이프, 1:스타일, 37:전경폰트색, 44m:배경폰트색
- COLORED TEXT(ANSI)
PREVIOUS섹션 2. 쉘 기초 명령어