일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 10km
- 성수대교
- 달리기
- 뚝섬유원지
- 정보처리기사
- 대구
- 자전거
- 유산소
- GitHub
- 맛집
- 소모임
- 힐링
- Run The Bridge
- Grafana
- docker
- 한강
- Linux
- zabbix
- Python
- Shell
- 대전
- Kubernetes
- 중식
- 하체
- Podman
- 2021
- 건대입구역
- 러닝
- DSEC
- 오답노트
- Today
- Total
Run The Bridge
shell script master -7- 본문
0. 입력과 출력
bash의 입력
- 명령 줄 인수
- 환경 변수
- 파일
- 파일 기술자(file descriptor)로 표현 가능한 파이프, 터미널, 소켓 등
bash의 출력
- 파일
- 파일 디스크립터로 표현 가능한 다른 것
- 다른 프로그램에 명령 줄 인수로
- 혹은 다른 프로그램에 환경 변수의 형태로 넘길 수도
1. 위치 매개 변수
다음과 같은 이미지 파일들이 존재한다.
-rw-r--r--. 1 root root 0 Jan 6 22:16 Balloon.jpg
-rw-r--r--. 1 root root 0 Jan 6 22:16 Candy.jpg
-rw-r--r--. 1 root root 0 Jan 6 22:16 glob.gif
-rw-r--r--. 1 root root 0 Jan 6 22:16 settings_down.png
-rw-r--r--. 1 root root 0 Jan 6 22:16 settings_up.png
-rw-r--r--. 1 root root 0 Jan 6 22:16 shadingimage.tiff
-rw-r--r--. 1 root root 0 Jan 6 22:16 smaller.tiff
---
이 image 파일들 중 확장자가. png 인 것을. JPG로 바꿔보자.
#!/bin/bash
for name in *.$1
do
mv $name ${name%$1}$2
done
예전에 파일들을 ls 해서 입력할 때 $(ls -l)이 아니고 그냥 *.*를 하면 입력이 되었던 것처럼 특별한 인용부호는 써주지 않는다.
$1에는. png라는 값이 들어갈 것이고,
$name에는 png확장자를 가지는, 즉 settings_up, down.png가 들어간다.
$[name%$1}은 예전에 배웠듯이 뒤에서부터 $1을 찾아 제거하고, $2를 붙이는 명령어이다.
아래 블로그 위치에서 Ctrl+F를 누르고 'teststring'를 검색하면 예시가 잘 나와있다.
https://anfrhrl5555.tistory.com/166
shell script master -3-
0. 쉘 스크립트란 무엇인가? 쉘(shell)은 명령 인터프리터로 사용자가 O/S에 대화식(interactively)으로 명령을 내리거나, 명령을 일괄(batch)적으로 실행할 수 있는 기능을 제공하는 응용 프로그램 Kernel
anfrhrl5555.tistory.com
※ 추가로 위치 매개 변수가 $9를 넘어 10이 되면 $10이 아니고, ${10}처럼 표현해주어야 한다.
2. 환경변수와 export
locale -a # 지역별 언어 패키지를 확인할 수 있다.
---
date 명령어를 사용했을 때, 한국어가 나오게 만들어 본다.
LANG=ko_KR.UTF-8 date # 1회성
2022. 02. 06. (일) 23:34:29 KST
---
다음과 같이 입력한다.
LANG=ko_KR.UTF-8
echo $LANG
ko_KR.UTF-8
---
date
2022. 02. 06. (일) 23:35:46 KST
하지만 reboot시, 원래의 en_US.UTF-8로 돌아온다.
---
간단하게 스크립트 파일을 작성해서 항상 ko_KR를 환경변수에 저장해 본다.
#!/bin/bash
echo $LANG in locale.sh
---
subshell에서도 유요 한 지 확인한다.
echo $LANG; ( echo $LANG in subshell: ); echo $LANG
ko_KR.UTF-8
ko_KR.UTF-8 in subshell:
ko_KR.UTF-8
---
다음처럼 환경변수가 아닌, 일반 변수로 LANG1을 만든다.
LANG1=ko_KR.UTF-8
#!/bin/bash
echo $LANG1 in locale.sh
---
LANG1의 값을 확인하고, 스크립트를 실행시켜 준다.
echo $LANG1
ko_KR.UTF-8
./locale.sh
in locale.sh
일반 변수 LANG1에는 실행결과가 다른 것을 알 수 있다. → 즉 상속이 일어나지 않는다.
그러면 서브 쉘에서는 어떨까? → 유요 하다.
echo $LANG1; ( echo $LANG1 in subshell: ); echo $LANG1
ko_KR.UTF-8
ko_KR.UTF-8 in subshell:
ko_KR.UTF-8
---
스크립트 파일에서도 LANG1을 유용하게 하는 방법 → export를 사용해준다.
export LANG1=ko_KR.UTF-8
./locale.sh
ko_KR.UTF-8 in locale.sh
---
linux에서 환경변수를 확인하는 'env'명령을 통해 LANG1을 확인한다.
env | grep -i LANG1
LANG1=ko_KR.UTF-8
3. 변수의 범위(스코프)
다음의 변수를 선언한다.
year=2020
---
함수를 하나 생성해서, 외부 변수가 함수에도 영향을 미치는지 확인한다.
function sub() { echo year=${year} in function; };sub
year=2020 in function
함수 내부에서도 유요함이 확인되었다.
---
그럼 함수 내부에서 값 변경이 외부에서까지 영향을 미칠까?
function sub(){ echo year=${year} in function; year=4050;};sub ; echo year=${year} in outer
year=2020 in function
year=4050 in outer
함수 안에서 'year=4050'으로 바꾸고 함수 밖에서 출력했을 때, year 값이 바뀌는 것을 확인할 수 있다.
---
echo 'echo year=$year' > mydate.sh
# vi mydate.sh
echo year=$year
---
스크립트 바깥에서 선언된 변수가 스크립트 내에서 접근이 되는지를 확인한다.(될 리가 없지 ㅋㅋ)
./mydate.sh; echo year=$year in outer
year=
year=4050 in outer
---
스크립트 파일을 간단하게 고치고, 스크립트 바깥에서 접근이 되는지를 확인한다.
# vi mydate.sh
echo year=$year
year=9999
./mydate.sh; echo year=$year in outer
year=
year=4050 in outer
안된다.
---
그렇다면 서브 쉘에서의 변수 범위는 어떻게 될까?
year=2020;( echo year=${year} in inline; year=4050; ); echo year=${year} in outer
year=2020 in inline
year=2020 in outer
최초 바깥에서 year=2020으로 year을 초기화시켜주었기 때문에 () 안에서 year은 2020을 담고 있고, inline; 이후에 year를 4050으로 초기화했지만, 서브 쉘에서 변경된 year=4050은 변경되지 않는다
그리고 바깥에서 year=2020을 선언해놨기에, 마지막 echo year=${year} 부분에도 2020이 출력되는 것을 알 수 있다.
※ 서브 쉘은 기본적으로 변수를 복제하여 사용하는 특성으로 이해하자.
---
그러면 인라인 그룹'{}'으로 바꿔본다면?
ear=2020;{ echo year=${year} in inline; year=4050; }; echo year=${year} in outer
year=2020 in inline
year=4050 in outer
인라인 그룹 안에서 선언된 변수는, 인라인 그룹을 벗어나도 영향을 끼치는 것을 알 수 있다.
※ 인라인 그룹은 기본적으로 명령어를 묶어놓은 것뿐, 다른 서브 쉘이 아니기 때문에 가능한 것
export의 범위에 대해서 알아본다.
export year=2020;./mydate.sh; echo year=$year in outer
year=2020
year=2020 in outer
env | grep year
year=2020
아까도 보았듯이, mydate.sh에 존재하는 'year=9999'는 스크립트를 벗어나서는 효과가 없다.
우선적으로 export을 통해 상속된 year=2020이 뒤에 나오는 year=$year에 값이 들어간 것을 확인할 수 있다.
※ 쉘 스크립트는 기본적으로 변수에 관한 한 sandbox로 이해한다.
변수와 export에 범위는 한 번에 이해하기 어려워 보인다.
여러 번 봐야 할 듯...
4. 파일 디스크립터
- 프로그램이 파일을 참조하는 방식이거나, 파일(파이프, 장치, 소켓 또는 터미널)처럼 작동하는 다른 리소스를 참조하는 방법
- FD는 데이터 소스에 대한 포인터와 비슷하거나, 혹은 기록 가능한 장소 같은 것
- FD에서 읽거나 쓸 때 FD의 리소스에서 데이터를 읽거나 쓰게 됩니다.
표준 입력(stdin) | 파일 디스크립터 0 |
표준 출력(stdout) | 파일 디스크립터 1 |
표준 오류(stderr) | 파일 디스크립터 2 |
---
다음과 같이 echo를 통해 출력하면, 파일 디스크립터 1번 표준 출력 장치를 사용한 것이다.
echo hello world
hello world
즉, echo 명령어는 stdout를 사용한다.
---
이러한 에러 메시지는 표준 오류 출력장치를 통한다.
ls dir3333333333
ls: cannot access dir3333333333: 그런 파일이나 디렉터리가 없습니다
---
다음과 같이 사용자의 입력을 받는 명령어를 사용하면 표준 입력 stdin을 이용한다.
read -p "key press: "
key press: k
5. 리다이렉션(<, <<, >, >>)
다음과 같이 '>'를 사용해서 출력 결과를 프롬프트에 뿌리지 않고, seagull.txt라는 파일에 저장된다.
echo "The seagull that files the highest sess the farthest" > seagull.txt
cat seagull.txt
The seagull that files the highest sess the farthest
---
다음과 같은 파일 디스크립터 stdout을 사용해도 똑같은 결과를 볼 수 있다.
echo "The seagull that files the highest sess the farthest" 1> seagull.txt
---
오류를 나타내는 파일 디스크립터 stderr 2번을 사용한다.
ls dir3333
ls: cannot access dir3333: 그런 파일이나 디렉터리가 없습니다
ls dir333 2> err.log
cat err.log
ls: cannot access dir333: 그런 파일이나 디렉터리가 없습니다
---
'>>'를 두 개 사용하면 append의 뜻을 가지고, '>'는 파일이 없다면 생성되고, 있다면 overwrite 되는 방식이다.
ls dir4444 2>> err.log
cat err.log
ls: cannot access dir333: 그런 파일이나 디렉터리가 없습니다
ls: cannot access dir4444: 그런 파일이나 디렉터리가 없습니다
---
다음의 파일을 생성한다.
echo ABCD > file1
echo 1234 > file2
두 개의 파일을 하나로 병합할 수도 있다.
cat file1 file2 > file
cat file
ABCD
1234
---
read의 내용을 읽어서 파일에 반영한다. '<'는 input으로 파일을 입력받는다.
while read v; do echo $v; done<file
ABCD
1234
---
정상적인 메시지는 steven.txt로 저장된다.
오류 메시지 또한 리다이렉트를 걸어서 표준 에러또한 표준 출력장치인 1번으로 들어간다.
echo "Jurassic Wolrd" > steven.txt 2>&1
사실상으로 모든 메시지는 steven.txt로 저장된다.
'2>&1'로 명시하지 않고 '2>1'로 작성하면 '1'이라는 파일이 생성된다.
---
다음의 명령어는 steven.txt라는 파일은 존재하지만 lucas.txt 파일이 존재하지 않아, 에러를 발생시키는데
표준 에러를 표준 출력인 1번으로 리다이렉션 시킨 것이다.
즉 '2>&1'가 없어도 같은 결과가 나오지만, 파일 디스크립터를 사용함으로써 컨트롤하기에 유용해 보인다.
grep -i "Star wars" steven.txt lucas.txt 2>&1
grep: lucas.txt: 그런 파일이나 디렉터리가 없습니다
echo $?
2
감사합니다.
'Cloud > Linux' 카테고리의 다른 글
shell script master -9- (마지막) (0) | 2022.01.27 |
---|---|
shell script master -8- (0) | 2022.01.27 |
shell script master -6- (0) | 2022.01.27 |
shell script master -5- (0) | 2022.01.21 |
shell script master -4- (0) | 2022.01.13 |