리눅스 서버를 자동화하여 관리하기 위한 쉘 스크립트(Shell Script) 심화 강좌를 정리합니다.
출처 : inflearn
1. 입력과 출력(Input and Output)
Bash 스크립트의 입력 및 출력은 복잡한 주제입니다.
Bash 스크립트 입력은 다음처럼 다양한 방법이 가능합니다.
1. 명령 줄 인수
2. 환경 변수
3. 파일
4. 파일 기술자(file descriptor)로 표현 가능한 파이프, 터미널, 소켓 등
Bash 스크립트의 출력은 다음처럼 다양한 형식이 가능합니다.
1. 파일
2. 파일 디스크립터로 표현 가능한 다른 것
3. 다른 프로그램에 명령 줄 인수로
4. 혹은 다른 프로그램에 환경 변수의 형태로 넘길 수도
2. 위치 매개 변수
$1,$2,$3 …${10},${11} 에 위치 매개 변수라는 용어를 사용함.
#!/bin/bash
# rename.sh
# 확장자 변경의 예
for name in *.$1
do
mv $name ${name%$1}$2
done
AWS_TEST:/home/shkim/edu/shell_cmd/images$ ls
Balloon.jpg Candy.jpg drill glob.gif settings_down.png settings_up.png shadingimage.tiff smaller.tiff
AWS_TEST:/home/shkim/edu/shell_cmd/images$ ../rename.sh png JPG
AWS_TEST:/home/shkim/edu/shell_cmd/images$ ls
Balloon.jpg Candy.jpg drill glob.gif settings_down.JPG settings_up.JPG shadingimage.tiff smaller.tiff
3. 환경변수와 export
로그아웃 후 재접속 하여 date 명령을 치면 환경변수는 원상복귀 됨.
AWS_TEST:/home/shkim$ date
Wed May 4 00:46:11 KST 2022
AWS_TEST:/home/shkim$ LANG=ko_KR.UTF-8 date
2022. 05. 04. (수) 00:46:26 KST
AWS_TEST:/home/shkim$ date
Wed May 4 00:46:30 KST 2022
AWS_TEST:/home/shkim$ echo $LANG
en_US.UTF-8
AWS_TEST:/home/shkim$ LANG=ko_KR.UTF-8 #환경변수 지정
AWS_TEST:/home/shkim$ date
2022. 05. 04. (수) 00:47:30 KST
bash 자식 프로세스에게 기존 환경변수값이 상속됨.
AWS_TEST:/home/shkim$ echo $LANG
ko_KR.UTF-8
AWS_TEST:/home/shkim$ bash
AWS_TEST:/home/shkim$ echo $LANG
ko_KR.UTF-8
#!/bin/bash
echo $LANG in locale.sh
스크립트 내에서도 locale 값이 유지 됨
AWS_TEST:/home/shkim$ ./locale.sh
ko_KR.UTF-8 in locale.sh
# subshell 에서도 유효함
AWS_TEST:/home/shkim$ echo $LANG; ( echo $LANG in subshell; ); echo $LANG
ko_KR.UTF-8
ko_KR.UTF-8 in subshell
ko_KR.UTF-8
AWS_TEST:/home/shkim$ LANG1=ko_KR.UTF-8
# locale.sh
#!/bin/bash
echo $LANG1 in locale.sh # 수정
# 일반변수 LANG1 에서는 상속이 일어나지 않음
AWS_TEST:/home/shkim$ ./locale.sh
in locale.sh
# 일반변수에서의 LANG1 은 서브쉘에서 유효함
AWS_TEST:/home/shkim$ echo $LANG1; ( echo $LANG1 in subshell; ); echo $LANG1
ko_KR.UTF-8
ko_KR.UTF-8 in subshell
ko_KR.UTF-8
# 일반변수의 LANG1을 유효하게 하려면 export 를 사용하면 됨.
AWS_TEST:/home/shkim$ export LANG1=ko_KR.UTF-8
AWS_TEST:/home/shkim$ ./locale.sh
ko_KR.UTF-8 in locale.sh
결론 export 된 변수는 환경변수이다.
4. 변수의 범위(스코프)
쉘 변수는 기본적으로 전역변수(광역변수)라는 점을 확인
# 함수바깥에서 선언된 변수가 함수 내에서 접근이 되는지를 확인
AWS_TEST:/home/shkim$ year=2020
AWS_TEST:/home/shkim$ function sub(){ echo year=${year}} in function; };sub
year=2020 in fuction
AWS_TEST:/home/shkim$ function sub(){ echo year=${year}} in function; year=4050;};sub; echo year=${year} in outer
year=2020 in function
year=4050 in outer
AWS_TEST:/home/shkim$ echo 'echo year=$year' > mydate.sh
AWS_TEST:/home/shkim$ chmod +x mydate.sh
# 스크립트 바깥에서 선언된 변수가 스크립트 내에서 접근이 되는지를 확인
AWS_TEST:/home/shkim$ ./mydate.sh; echo year=$year in outer
year=
year=4050 in outer
# 스크립트 수정
AWS_TEST:/home/shkim$ vi mydate.sh
echo year=$year
year=9999
# 스크립트 내에 변수선언 내용은 스크립트 내부에서만 유효함.
# 쉘스크립트는 기본적으로 변수에 관한한 sandbox로 이해
AWS_TEST:/home/shkim$ ./mydate.sh; echo year=$year in outer
year=
year=4050 in outer
# 서브쉘 바깥에서 선언된 변수가 서브쉘 내에서 접근이 되는지를 확인
AWS_TEST:/home/shkim$ year=2020;( echo year=${year} in inline; year=4050); echo year=${year} in outer
year=2020 in inline
year=2020 in outer
# 서브쉘 내에서 복제가 되서 실제로 상속효과가 일어남
# 서브쉘은 기본적으로 변수를 복제하여 사용하는 특성으로 이해하자.
# 인라인 바깥에서 선언된 변수가 인라인 내에서 접근이 되는지를 확인
# 인라인 그룹 {} 뒤에는 항상 ; 을 잊지 말자.
AWS_TEST:/home/shkim$ year=2020;{ echo year=${year} in inline; year=4050;}; echo year=${year} in outer
year=2020 in inline
year=4050 in outer
# 인라인 그룹은 기본적으로 명령어를 묶어놓은 것 뿐이다.
# export 한 변수, 위에서 보면 mydate.sh 안 year 변수에는 9999가 선언되있음.
AWS_TEST:/home/shkim$ export year=2020; ./mydate.sh; echo year=$year in outer
year=2020
year=2020 in outer
# 쉘스크립트는 기본적으로 변수에 관한한 sandbox로 이해
5. 파일 디스크립터
파일 디스크립터(FD : File Descriptors)는 프로그램이 파일을 참조하거나, 파일(파이프, 장치, 소켓 또는 터미널)처럼 작동하는 다른 리소스를 참조하는 방법입니다. FD는 데이터 소스에 대한 포인터와 비슷하거나, 혹은 기록 가능한 장소 같은 것입니다. FD에서 읽거나 쓸 때 FD의 리소스에서 데이터를 읽거나 쓰게 됩니다.
- 표준 입력(Stdin) : 파일 디스크립터 0
- 표준 출력(Stdout) : 파일 디스크립터 1
- 표준 오류(Stderr) : 파일 디스크립터 2
# Stdout
AWS_TEST:/home/shkim$ echo hello world
hello world
# Stderr
AWS_TEST:/home/shkim$ ls dir333333
ls: dir33333에 접근할 수 없습니다 : 그런 파일이나 디렉터리가 없습니다
# Stdin
AWS_TEST:/home/shkim$ read -p "key press"
key press
6. 리다이렉션
# 표준출력
AWS_TEST:/home/shkim$ echo "The seagull that flies the highest sees the farthest" > seagull.txt
AWS_TEST:/home/shkim$ cat seagull.txt
The seagull that flies the highest sees the farthest
# 표준출력
AWS_TEST:/home/shkim$ echo "The seagull that flies the highest sees the farthest" 1> seagull.txt
# 표준 에러
AWS_TEST:/home/shkim$ ls dir3333
ls: cannot access dir3333: No such file or directory
AWS_TEST:/home/shkim$ ls dir3333 2> err.log # overwrite 파일이 있을 경우 덮어씀
AWS_TEST:/home/shkim$ cat err.log
ls: cannot access dir3333: No such file or directory
# append : >> 기존 파일에 추가
AWS_TEST:/home/shkim$ ls dir4444 2>> err.log
AWS_TEST:/home/shkim$ cat err.log
ls: cannot access dir3333: No such file or directory
ls: cannot access dir4444: No such file or directory
AWS_TEST:/home/shkim$ echo ABCD > file1
AWS_TEST:/home/shkim$ echo 1234 > file2
AWS_TEST:/home/shkim$ cat file1 file2 > file # 2개의 파일이 결합됨.
AWS_TEST:/home/shkim$ cat file
ABCD
1234
AWS_TEST:/home/shkim$ while read v; do echo $v; done<file #input 파일을 입력 받음
ABCD
1234
# 표준 출력장치로 나온 메시지가 방향을 틀어 steven.txt로 들어가고
# 표준 에러로 출력될 메시지 또한 표준출력으로 방향이 변경되었으며 사실상 모든 메시지는 steven.txt에 남게된다.
AWS_TEST:/home/shkim$ echo "Jurassic World" > steven.txt 2>&1
# lucas.txt 파일은 발견되지 않는다.
# 표준 출력장치가 아닌 표준에러로 에러메시지가 나올 것이었지만 에러메시지는 리다이렉트로 인해 표준에러가 아닌 표준출력으로 에레메시지가 출력됨.
AWS_TEST:/home/shkim$ grep -i "Star Wars" steven.txt lucas.txt 2>&1
grep: lucas.txt: No such file or directory
AWS_TEST:/home/shkim$ echo $?
2
PREVIOUS섹션 6. 배열
NEXT섹션 8. 유용한 유틸리티