3장에서는 셸과 스크립팅을 다룬다.
스크립트는 서버 관리자라면 정말 자주 사용하는 것 같다. (복잡하지 않은 작업들)
- 분 단위 자원 사용률 기록 / 주기적인 상태 확인
- 모든 서버들에 대해 파일을 전송해야 할 때
- 배치 Job 실행하기
- 서비스 기동, 중지하기
- 백업
고민했던 스크립트를 생각하면서 내용을 정리해 본다.
- 터미널
- 텍스트로 된 사용자 인터페이스를 제공하는 프로그램
- TERM이라는 환경변수에 사용 중인 터미널 에뮬레이터값이 저장되어 있음 (출력방식)
- 셸
- 터미널 내부에서 실행되는 명령 인터프리터 역할을 하는 프로그램
- 스트림
- 출력과 입력 시 프로세스 간 데이터를 전달하기 위한 통로
- 스트림은 FD(파일디스크립터)에 의해 관리됨
- 0, 1, 2 FD에 표준 입출력 스트림이 예약되어 있음
- 변수
# 셸 변수 정의 (set으로 확인 가능, env에는 보이지 않음)
$ set myvar=hello
$ set | grep myvar
myvar=hello
$ env | grep myvar
# 출력 없음
# 환경 변수로 변환 (export 후 env에서 보임)
$ export myvar
$ env | grep myvar
myvar=hello
터미널 셸과 스크립트 셸
터미널 환경에서의 설정값과 스크립트 실행 시의 설정값이 달라 예상치 못한 결과가 나타날 수 있어 알아둬야 할 것이 있다.
- 터미널 셸은 인터랙티브 셸로 실행
- 로그인 상태 및 사용자 설정 파일(~/.bashrc, ~/.profile 등)을 로드
- 스크립트 셸은 비인터랙티브 셸로 실행됩니다.
- 사용자 입력 없이 지정된 명령어를 순차적으로 실행
- 로그인 환경 설정 파일을 로드하지 않으며, 스크립트 자체에서 명시적으로 설정된 환경만 사용
동일한 셸 변수를 유지하고 싶다면
- 터미널 환경을 시작할 때의 설정파일을 로드하는 명령어를 스크립트 맨 위에 입력
- 환경 설정용 파일 ex).ini 을 통해 원하는 환경변수를 주입해 줄 수 있음
- 스크립트 실행 시 source .sh로 실행하면 현재 터미널의 환경변수를 유지할 수 있음
행 탐색과 조작
- Ctrl + a
- 행의 시작으로 커서 이동
- Ctrl + e
- 행의 마지막으로 커서 이동
- Shift + g
- 맨 마지막 행으로 커서 이동
- Ctrl + b
- 위 페이지로 이동
- Ctrl + d
- 아래 페이지로 이동
인간 친화적인 셸
책에서 인간친화적인 모던 셸을 추천하고 있다.
대표적인 것은 fish 셸과 zsh 인 것 같다.
zsh은 들어보기도 했고, bash shell을 호환한다고 하니 흥미가 좀 생겼지만 실제 회사에서 기본 bash shell이 아닌 다른 쉘들을 서버에 도입하기는 쉽지 않을 것 같다.. 그만한 이유가 있어야 하고 변화는 어디서 장애를 불러올지 모르기에..
zsh에서 5개의 시작 파일을 사용한다고 나오는데 bash shell도 마찬가지이다. 해당 시작 파일을 통해 계정마다 공통된 환경을 제공할 수 있으며 활용하기 나름이다.
나의 경우에는 각 계정별로 명령 History를 저장하기 위해 해당 설정을 해놓았다.
### 계정 접속 시 공통으로 호출되는 profile
ubuntu@ip-172-31-130-226:/etc/skel$ cat /etc/profile
...
HISTTIMEFORMAT="%Y-%m-%d [%H:%M:%S] "
export HISTTIMEFORMAT
export HISTSIZE=5000 # 저장할 히스토리 크기
export HISTFILESIZE=10000 # 저장할 파일 크기
timestamp=$(date +"%Y%m%d_%H%M%S")
export HISTFILE="/home/History/${USER}_history_${timestamp}"
### 계정 생성 시 공통으로 내려지는 bash_logout파일
ubuntu@ip-172-31-130-226:/etc/skel$ cat .bash_logout
history -a > $HISTFILE
셸은 사용하기 나름이고 아직까지는 bash shell 말고는 사용해 본 게 없어서 다른 셸을 선뜻 설치하고 테스트해 보는 게 끌리지 않았다..
fish shell 설치
https://jungmonster.tistory.com/253
[Linux/Tool] 우분투 Fish Shell 사용하기
Ubuntu 17.10 친구가 fish shell을 추천해서 설치 해봤습니다. https://fishshell.com/ fish shell 설치 sudo apt-add-repository ppa: fish-shell/release-2 sudo apt-get update sudo apt-get install fish 쉘 지정 chsh -s /usr/bin/fish 이후 쉘
jungmonster.tistory.com
zsh 설치
Ubuntu에 Oh My Zsh 설치
# zsh-syntax-highlighting git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting # zsh-autosuggestions git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~
log4cat.tistory.com
tmux - 터미널 멀티플렉서
두 개의 창에서 상호의존적인 작업이 필요할 때 다중화를 통해 터미널 사용을 개선하는 방법
터미널 멀티플렉서를 사용해야 하는 이유가 무엇일까 생각해 봤다.
- ssh 접속 시 TMOUT=0 설정을 통해 터미널이 종료되지 않게 설정해 놓으면 끊기지 않는다?
- ssh 옵션에 의해 접속 종료될 수 있음
- 네트워크가 끊기면 접속 종료될 수 있음
- tmux 사용 시 접속이 끊기더라도 세션이 살아있어 작업환경이 보존된다!
- 다중 작업이 필요하면 터미널 여러 개 열면 되는 거 아닌가?
- 언제 끊길지 모르는 것, 어떤 터미널에서 어떤 작업을 하고 있었는지 추적하기 헷갈리는 것
해당 이유만으로도 충분히 tmux를 사용하는 게 좋다고 생각하여 명령어를 연습해 볼 생각이다.!
명령어설명 - 커맨드 트리거 - Ctrl+b
새로운 세션 생성 | tmux new -s <session_name> |
세션 리스트 확인 | tmux list-sessions |
세션 분리(나오기) | Ctrl-b d |
세션 다시 연결 | tmux attach -t <session_name> |
세션 종료 | 특정 세션 종료 tmux kill-session -t <session_name> 전체 종료 tmux kill-server |
새 창 열기 | Ctrl-b c |
창 닫기 | Ctrl-b & |
창 이동 | 다음 창으로 이동: Ctrl-b n 이전 창으로 이동: Ctrl-b p |
패널 분할 | 세로 분할: Ctrl-b % 가로 분할: Ctrl-b " |
패널 이동 | Ctrl-b o |
패널 닫기 | Ctrl-b x |
스크립팅
고급 I/O
echo 대신 printf 사용하기
- 출력할 때 동일한 형식으로 출력하기 좋음 - 스크립트에서의 삐뚤삐뚤한 출력을 방지할 수 있음!
echo " Birth Name"
ls -lrt | grep -v total | while read i
do
n=`echo $i | awk '{print $9}'`
birth=`stat $n | grep Birth`
printf "%-20s %20s\n" "$birth" "$n"
done
echo ""
ShellCheck
스크립트를 올바르게 사용하고 있는지 동일한 형식으로 스크립트를 짜고 있는지 체크하는 데 사용하면 좋을 것 같다
- 스크립트라는 게 프로그래밍과 같이 다양한 방식으로 구현할 수 있기 때문에 컨벤션을 사용하자..
- #!(해시뱅)을 선언하여 어떤 쉘 인터프리터를 사용할지를 선언해야 한다 (이식성)
- read -r 없이 사용하면 \ 처리 시 문제가 발생할 수 있음
- ls | grep 문을 사용하면 filename이 아닌 얘들도 읽을 수 있으니 다른 방법을 사용해라
- 백틱 말고 $() style을 사용해라
- 변수는 Double quote로 word split 등을 방지해라 "$i" (split으로 인해 잘못된 명령어가 실행될 수 있음)
수정 후
#!/bin/bash
echo " Birth Name"
find . -maxdepth 1 -not -name '.' -type f | while read -r i
do
n=$(echo "$i" | awk '{print $9}')
birth=$(stat "$n" | grep Birth)
printf "%-20s %20s\n" "$birth" "$n"
done
echo ""
Shellcheck도 자주 사용할 것 같다!
'Study' 카테고리의 다른 글
[Linux] 모던 리눅스 교과서 5장 - 파일시스템 (0) | 2024.12.01 |
---|---|
[Linux] 모던 리눅스 교과서 4장 - 접근제어 (0) | 2024.11.24 |
[Linux] 모던 리눅스 교과서 1,2장 (1) | 2024.11.10 |
[Openstack] Devstack 설치 과정 알아보기 (0) | 2024.10.13 |
[Openstack] DevStack을 이용한 Openstack 설치 (1) | 2024.10.09 |