전자 도서관 이용하여 해당 도서를 읽고 포스팅 합니다
*무료 전자도서관 이용 후기
https://dev-ljw1126.tistory.com/395
*도서 구매 링크
https://www.aladin.co.kr/shop/wproduct.aspx?ItemId=90620424
1장. 다른 컴퓨터를 리모트로 조작하고 싶어 (ssh)
SSH (Secure SHell)
- 다른 PC에 네트워크 경유로 로그인 해서 자기 PC처럼 조작할 수 있다
- 통신 경로는 암호화되어 안전하다
접속 방법
$ ssh 계정@IPv4주소
# 또는
$ ssh 계정@HostId
2장. 임시로 관리자 권한을 얻고 싶어 (sudo)
접근 권한
- 리눅스는 모든 파일이나 폴더에 "누구의 것인가", "누가 읽고 쓸 수 있나" 라는 권한을 설정한다
- 접근 권한은 파일 소유자가 아니면 바꿀 수 없지만 예외로 root 가 있다
root
- 관리자 권한을 가진 특별한 사용자
- 파일 접근 권한을 자유롭게 변경하거나 다른 사람 파일을 수정하는 등 무엇이든지 가능하다
- 그러므로 root 암호는 철저하게 관리해야 하고, 우분투의 경우 root로 로그인하는 걸 기본적으로 막기도 한다
일반 관리자 사용자
- root는 미리 정한 특정 사용자에게 root와 같은 권한을 부여할 수 있다
root는 언제나 특권을 사용할 수 있지만 일반 관리자는 필요할 때 암호 입력하여야 사용할 수 있다
- $ sudo 사용할 명령어 형식으로 관리자 권한으로 실행 가능
sudo(superuser do) : 특정 계정에 대해 root 권한 전체 또는 지정한 일부만 사용 가능하도록 권한 부여/관리/제어/실행을 담당
*참고. 우분투 계정 추가, sudo 권한 부여
https://dev-ljw1126.tistory.com/294
우분투에서 root로 로그인할 경우
$ sudo -i
# 또는
$ sudo su
3장. 다양한 문자열을 한 번에 검색하고 싶어 ( grep )
grep 명령어
- 파일 내용을 빠짐없이 확인해서 찾는 문자열이 포함되었는지 조사해준다
- global regular expression print(파일 전체에서 정규표현식과 일치하는 위치를 출력하라) 약어
사용 형식
$ grep -r "검색하고 싶은 문자열" /home/docs
-r : --recursive, 서브(하위) 폴더까지 검색하도록 지정
파일 내용을 대소문자 무시하고 정규 표현식 사용하여 검색 (-E 옵션)
$ grep -r -i -E "(do|something)" 디렉토리 경로
-i : --ignore-case 대소문자 구분을 무시, (기본값은 --no-ignore-case)
-E : --extended-regexp, 정규표현식 사용
*참고. 유용한 정규표현식 테스트 사이트
4장. 터미널에서도 대화형으로 파일을 편집하고 싶어 (vim)
Vim 설치
$ apt-get install -y vim
vim 환경 설정은 home 디렉토리의 .vimrc 파일에서 관리
Vim 모드
- 노멀(normal) 모드 : 각 모드에서 esc 키 누르면 전환, 일반적으로 홈 화면 역할
- 끼워넣기(insert) 모드 : i 또는 a 누르면 전환
- 치환(replace) 모드: r누르면 한자리 변환 가능, R누르면 커서 위치부터 변환 가능(키보드에 insert 눌렀을 때와 같음)
- 선택(select) 모드 : v 또는 shift + v 누르면 전환, 마우스로 영역 드래그 하듯이 키보드로 영역 선택
- 검색(search) 모드 : 노멀 모드에서 / 눌러 검색 모드로 들어가서 검색하고 싶은 문자열 입력 후 Enter (ex. /검색문자열)
다른 모드에서 노멀 모드로 돌아갈 때는 esc 를 누르면 된다
Vim Cheat Sheet
*참고. 개인 작성한 Vim 기본 명령어 정리
(1) Vim 친해지길 바래 - 1 https://www.notion.so/Vim-1-d40ce37e590249d493e7c844d5cd95f6
(2) Vim 친해지길 바래 - 2 https://www.notion.so/Vim-2-ebf2790676784a0db277b5fc8faa073f
5장. vim 에서도 복사 & 붙이기 & 되돌리기를 하고 싶어 ( yank )
- GUI 애플리케이션과 콘솔 애플리케이션 환경에서 ctrl + c 와 ctrl + v 는 다르게 인식되어 동작한다(p39)
- Vim에서는 복사할 때 Y 키를, 붙여넣기 할 때 P 키를 사용한다
복사 yank
- yank는 "끌어당기다"는 의미로 집게로 이를 뽑는 것 같은 상황에서 쓰는 단어이다
- visual 모드 활성화 > 영역 선택 > y 키 누르게 되면 해당 영역이 복사된다 (복사값은 register에 저장됨)
- yy 키를 누를 경우 한 라인(줄) 복사
붙여넣기 Paste
hello를 yank로 복사하고 커서가 다음과 같이 위치할 때
- p 키를 누를 경우
hello hello
커서가 위치한 곳에서 한 칸 띄운 후 붙여 넣는다
- shift + p 키 누를 경우
hellohello
커서가 위치한 곳에 바로 붙여 넣는다
되돌리기(Undo), 앞으로 되돌리기(Redo)
- Vim 편집 중에 작업 취소하거나 앞 작업으로 되돌리기 할 때 유용하게 사용 가능
- Undo : u 키
- Redo : shift + r 키
*참고. 개인 작성한 Vim 기본 명령어 정리
(1) Vim 친해지길 바래 - 1 https://www.notion.so/Vim-1-d40ce37e590249d493e7c844d5cd95f6
(2) Vim 친해지길 바래 - 2 https://www.notion.so/Vim-2-ebf2790676784a0db277b5fc8faa073f
Ctrl + z 눌렀을 때
- 실행 중인 애플리케이션이 일시 정지되고 명령어 입력 상태로 돌아가게 된다
- GUI 애플리케이션의 백그라운드 창 모드와 비슷한 상태이다
- 일시 정지된 애플리케이션은 fg 명령어로 다시 실행 가능하다
6장. 갑작스러운 네트워크 끊김에서 복귀하고 싶어 (가상 단말 : tmux)
tmux 자체의 기능을 사용할 때는 우선 ctrl + b (Prefix Key)를 누른 후 실제로 하고 싶은 작업 키를 지정해야 한다
Prefix Key 사용하는 이유는 다른 조작법과 겹치지 않도록 하기 위함이다
예) ctrl + c 프로세스 종료, ctrl + r 되살리기, ctrl + z 프로세스 일시 정지
가상 단말은 콘솔 환경에서 GNOME(그놈) 단말이 하는 것과 같은 걸 하는 애플리케이션이다
(가상단말이 조상이고, GNOME이 후손)
서버와의 연결이 끊기는 경우
- 일반적으로 서버에서는 로그아웃으로 보기때문에 작업중이던 프로세스도 전부 종료 된다
- 반면 tmux(가상단말) 사용하는 경우 ssh 접속이 끊긴 사용자가 로그아웃 상태가 되더라도 계속 동작하는 특징이 있다
가상단말에서 실행한 애플리케이션도 함께 계속 동작하고 있다
다시 tmux에 연결하려면 아래의 명령어를 입력한다. (단, 1개의 tmux session 일때)
$ tmux attach
-- attach:접속하다
(이미지 출처 - https://helpful.knobs-dials.com/index.php/Screen_and_tmux)
tmux 기능 일부
각각 ctrl + b 누른 후
- d키(detach) : tmux 화면 밖으로 나오기
- c키(create) : 새로운 가상 화면 만들기
- n키(next) : 다음 화면으로 전환
- p키(previous) : 이전 화면으로 전환
참고. tmux 이외의 단말
- screen : tmux보다 오래 되었고, 설정이 어려워 사용이 불편하다
- byobu : tmux, screen 보다 편리하고 더 간단하게 사용할 수 있지만, 가상 단말을 통해 실행하는 어플리케이션에 영향을 많이 끼친다는 단점이 있다
참고. [Tmux] tmux를 써보자
https://gptjs409.github.io/infra/2019/07/29/tmux.html
7장. 다른 화면도 보면서 작업하고 싶어 (tmux 화면 분할)
tmux 화면 분할 및 단축키
① 가로 분할 : ctrl + b 입력 후 " 키 입력
② 세로 분할 : ctrl + b 입력 후 % 키 입력
③ 분할된 화면간 이동 : ctrl + b 입력 후 화살표 방향키 입력하여 화면 포커스 이동
④ 분할 화면 내 스크롤 : ctrl + b 입력 후 (위) [ 키또는 (아래) ] 키 누르면 스크롤 가능해짐, 종료는 Q키 또는 esc
-tmux는 가상 화면 스크롤 결과를 하나의 화면으로 GNOME 단말에 돌려주는데, GNOME 단말에서 보면 화면 내용이 넘치지 않아 스크롤 할 수 없음
-그래서 ④번과 같은 tmux 명령어 사용하여 스크롤 기능 지원
⑤ 분할 해제 : exit 입력
⑥ 화면 크기 조정 : ctrl + b 입력 후 ctrl 키 누르면서 방향키로 분할 경계선을 조정한다
8장. 최근 실행한 명령어를 호출하고 싶어 (명령어 이력)
용어
- gnome 단말 : GUI 환경에서 셸을 실행하기 위해 사용하는 것으로 셸 자체는 아니다
- zsh(z-shell) : 사용자가 콘솔 환경에서 대화식으로 명령어를 입력하면서 사용하는 소프트웨어가 셸이다
ㄴbash나 dash , z shell 많이 사용
ㄴ다양한 소프트웨어를 사용자 요구에 따라 실행하거나 조작을 돕는 게 셸의 역할이다
명령어 이력 확인
- 셸은 사용자 입력한 명령어를 기록해주고 나중에 호출할 수 있도록 명령어 이력기능을 지원한다
- vim ~/.bash_history명령어 실행하면 그 동안 입력한 이력이 기록되어 있어 확인가능하다
- 셸에서는 기본적으로 방향키 위 or 아래 눌러서 조회 가능
명령어 이력 검색 기능
검색 키워드 입력 후 몇번이고 누르면 입력한 내용을 포함한 이력항목만 순차적으로 찾는다
- 후방 검색(Reverse search) : ctrl + r
- 전방 검색(Search) : ctrl + s
ㄴ전방 검색의 경우 bash에서 아래와 같이 추가 설정이 필요하다
$ vim ~/.bashrc
# shift + g 눌러서 하단에 넣기
stty stop undef
ctrl + s의 경우 초기 상태에서 다른 조작이 할당되어 있는데 설정 변경 통해 bash에서 전방 검색으로 사용할 수 있도록 한다
참고. 셸(Shell) ?
리눅스나 BSD 같은 유닉스 계열 OS는 커널이라는 부품이 핵심인데 커널 기능은 인간이 그대로 사용하기에는 어렵고 조금만 실수해도 시스템이 망가질 수 있다. 그래서 조개처럼 속은 감추고 간단한 명령어로 대화식으로 조작할 수 있게 한 걸 셸이라고 부른다.
9장. 오래전에 실행한 명령어를 호출하고 싶어 (명령어 이력 검색)
명령어 이력의 경우 오래된 것부터 순서대로 지워진다
이력 사이즈 설정 수정
$ vim ~/.bashrc
# 아래와 같이 사이즈 조정
export HISTSIZE=10000
export HISTFILESIZE=10000
- HISTSIZE : 메모리에 저장할 이력의 최대 건수
- HISTFILESIZE : .bash_history에 저장할 이력의 최대 건수
-저장 후 재접속 하거나 source ~/.bashrc로 바로 반영할 수 있다
이력 동기화 설정
가상 단말과 명령어 이력은 궁합이 좋지 않은데, GNOME 단말에서 탭을 열거나 가상 단말로 새로운 화면을 열거나 각각 화면용으로 다른 bash가 실행될 경우 각자의 명령어 이력 복사본을 가지게 된다. 그러다보니 어떤 화면에서 실행한 명령어는 다른 화면의 bash 명령어 이력에서는 검색할 수 없다.
아래 설정을 추가하면, 어떤 명령어를 실행할 때 마다 .bash_history와 메모리의 명령어 이력이 동기화 된다
$ vim ~/.bashrc
# 아래 설정을 추가 후 저장
function share_history {
history -a
history -c
history -r
}
PROMPT_COMMAND='share_history'
shopt -u histappend
참고. SSH 로 명령어 실행
ssh 명령어 끝에 실행하고 싶은 명령어를 적으면 된다
$ ssh ubuntu@server /script/doSomething.sh
10장. 네트워크 건너서 파일을 복사하고 싶어 ( scp )
scp 명령어
- Secure CoPy 의 약어
- 네트워크를 통해서 파일을 복사하는 명령어
① scp 를 실행하면 우선 scp가 SSH를 호출한다
② 그리고 SSH 통신 경로를 사용해서 파일을 보낸다
B서버에서 현재 A 서버로 가져 올 경우
$ scp ubuntu@B서버IP:/tmp/sample.txt ~/
여러개 파일 또는 디렉토리 복사할 경우
# 와일드 카드를 사용하여 디렉토리내 *.txt 확장자 파일 모두
$ scp ubuntu@B서버IP:/tmp/*.txt ~/download/
# 디렉토리 전체 복사
$ scp -r ubuntu@B서버IP:/tmp/ ~/download/
-r(recursively) 옵션으로 디렉터리를 재귀적으로 복사
다른 C서버에서 다른 D서버로 파일 복사할 경우
$ scrp ubuntu@C서버IP:/tmp/sample.txt ubuntu@D서버IP:/tmp/
scp는 복사 원본이나 복사 대상에 다른 컴퓨터 파일을 지정하는 것 외에는 cp와 다르지 않다! (p78)
11장. 시스템 부하를 파악하고 싶어 ( top )
살펴 볼 부하 지표
① load average : CPU가 처리하게 될 작업 개수 뜻함, 1분당 평균 몇개의 일이 쌓이는지를 나타내는 값이다
-각 순서대로 1분간 평균, 5분간 평균, 15분간 평균 값을 나타낸다
-만약 작업량이 적으면 쌓인 작업량은 평균치로 0.1이나 0.2 정도로 무척 작음 (= CPU가 놀고 있다)
-반대로 작업이 쌓이게 되는 경우 (처리 속도보다 작업 발생 속도가 빠른 경우) load average가 높은 상태, 즉 과부하 상태인 것이다
-CPU 코어 만큼 한번에 일을 할 수 있는데, CPU 개수 만큼 가동 중인 경우 새로운 작업이 늘어나면 금방 과부하 상태가 될 가능성이 있어 좋지 않다
② %CPU : CPU 사용률
③ TIME+ : 실제로 CPU를 사용한 시간
과부하의 원인을 찾을 땐 "CPU 사용률이 높다", "CPU 시간도 길다" 와 같은 프로세스가 있는지 찾아보는게 빠르다 (p84)
c 키를 누르게 되면 아래와 같이 상세 표시 전환된다. 이를 통해 어떤 명령어인지 자세히 볼 수 있다
요약 정리
- load average >= CPU 코어수가 되면 과부하 상태
- CPU 사용률과 CPU 사용 시간 양쪽이 큰 프로세스는 과부하 원인의 가능성이 높음
- 과부하 원인인 프로세스는 kill 명령어로 종료함
*참고. 여러 프로세스를 동시에 종료하기
아래와 같이 kill 명령어 뒤에 PID(Process ID)를 스페이스로 띄어서 나열하면 된다
$ sudo kill 111 222 333
12장. 시스템 메모리 부족을 파악하고 싶어 (top 표시 전환)
CPU는 보통 작업 장소로 메인 메모리를 사용하지만 메모리 여유 공간이 부족하면 새로운 작업을 할 수 없게 된다
그렇게 되면 OS는 메모리에 있는 "최근에 사용하지 않은 데이터"를 정리해서 메모리 빈 공간을 만들어 낸다
- 스왑 : 스왑 인과 스왑 아웃 양쪽을 포함해서 부름
- 스왑 아웃 : 정리된 데이터를 하드 디스크로 옮기는 경우
- 스왑 인 : 반대로 스왑 아웃한 데이터가 필요 해지면 하드 디스크에서 메모리로 데이터를 되돌리는 경우
스왑은 OS가 알아서 관리하므로 각각의 프로그램은 메모리 상태를 신경쓰지 않아도 되지만 점점 더 메모리를 사용하여 스왑이 빈번히 발생할 경우 In/Out 대기 시간이 길어져 최악의 경우 디스크까지 가득 차 Out of Memory Killer(OOM Killer) 기능이 동작하게 된다
Out of Memory Killer(OOM Killer)
- OS가 멈추지 않도록 OS가 적당히 프로세스를 골라서 강제 종료 시킨다
- 이때 ssh 서비스를 종료 시킬 경우 서버를 재시작할 수 밖에 없다
요약 정리
- load average가 높아도 CPU 과부하 상태가 아닐 수도 있다
- 빈 메모리가 부족하면 > 스왑(디스크 I/O)이 자주 발생 > CPU 처리가 쌓임 > load average가 높아져서 시스템 반응이 나빠짐
- 스왑량이 급격히 증가한다면 주의가 필요하다
그 외 top 표시 항목을 정렬하는 방법은 아래와 같다
- 메모리 소비량 큰 순으로 정렬할 경우 shift + m키
- CPU 시간 순서로 나열할 경우 shift + t키
- CPU 사용량 순서로 나열할 경우 shfit + p키
13장. 로그 파일에서 필요한 줄만 뽑고 싶어 (파이프 라인 | )
리눅스는 아래와 같이 어떤 명령어의 실행 결과 출력을 그대로 다른 명령어로 넘길 수 있다
이렇게 쓰는 방법을 파이프 라인, 파이프 라고 부른다
less 명령어
-Unix 및 Unix 계열 운영 체제에서 사용되는 텍스트 파일을 화면에 표시하는 명령어이다
-less를 사용하면 파일을 스크롤하고 검색할 수 있다
압축형식에 따라 파일을 읽는 명령어 구분
- 비압축 텍스트 파일 : cat
- gzip (*.gz, *.tgz) : zcat
- zip (*.zip) : unzip
- xz (*.xz) : xzcat
파일 내용을 읽어 파이프 라인으로 전달 가능하다
요약 정리
- 파이프 라인( | )을 사용하면 명령어끼리 조합해서 사용 가능하다
- grep은 다른 명령어 출력을 가공하는 데도 사용 가능 하다 (=필터역할)
- zcat을 사용하면 압축된 로그 파일에서 바로 파이프 라인으로 연결 가능하다
14장. 작업 절차를 자동화하고 싶어 (쉘 스크립트)
쉘 스크립트
- bash나 zsh 같은 쉘로 실행하는 스크립트의 총칭
- 해야 할 작업을 전부 명령어로 표현할 수 있다면 작업 전체도 하나의 스크립트로 작성할 수 있다 (자동화 가능)
- 그리고 스크립트로 작성해두면 재사용 할 수 있다는 장점이 있다
스크립트 상단 #!/bin/bash
- #!은 셔뱅(shebang)으로 읽고, 스크립트를 실행하는 프로그램(인터프리터)를 지정
- 뒤에 프로그램 전체 경로를 적으면 스크립트를 실행하는 프로그램을 쉘이 자동으로 전환해준다
- 이 경우 /bin/bash , 즉 bash 가 처리하는 bash용 스크립트를 뜻한다
직접 실습
① hello.sh 생성
#!/bin/bash
echo "hello word"
② 권한 부여
새로 만든 쉘 스크립트는 실행 권한이 없으므로 chmod 명령어로 권한을 설정해야 한다
$ chmod +x hello.sh
③ 실행
$ ./hello.sh
hello world
$ ~/hello.sh
hello world
$ /home/hello.sh
hello world
추가. 명령어가 이상이 생겨서 그 시점에서 스크립트 실행을 중단하고 싶을 때는 아래 내용을 적는다
if [ $? != 0 ]; then exit; fi
- $? : 이전 명령어 실행값 (0 : 정상인 경우, 그외 : 비정상인 경우)
15장. 같은 문자열을 스크립트에서 재사용하고 싶어 (쉘 변수)
요약 정리
- 터미널이나 쉘 스크립트에서 변수명=문자열 이라고 작성하면 오른쪽 문자열이 값이고, 왼쪽에 있는 게 이름인 변수가 정의됨
- $변수명 또는 ${변수명} 으로 그 값과 동일하게 사용 가능
- 유지 보수하기 쉽도록 변수명은 변수에 저장될 내용을 잘 설명하는 이름을 사용하기
예시1. 명확한 변수명 짓기
#!/bin/bash
latest=/var/log/apache2/access.log
prev=/var/log/apache2/access.log.7.gz
cat $lated | analyza_latest.sh max
zcat $prev | analyza_prev.sh max
예시2. eval 명령어
#!/bin/bash
tar_extract="tar xfv"
tar_compress="tar cfv"
eval "$tar_extract file.tar.gz"
eval "$tar_compress direcotry"
- 변수명에는 _(언더 스코어)를 사용
- 문자열을 eval 명령어에 넘기면 명령어열로 실행 가능하다
참고. vim 치환 명령어 형식
:%s/원문/수정문
- 이외에도 범위를 지정하거나, 정규 표현식 사용하는 방법도 있다
16장. 작업 환경과 상태를 정해서 스크립트를 실행하고 싶어 (환경 변수)
환경 변수 (Environment Variable)
운영 체제에서 시스템 환경에 대한 정보를 저장하는 변수이다. 이러한 변수들은 시스템 전반에 걸쳐 프로그램이나 프로세스가 실행될 때 사용되며, 시스템 동작을 제어하고 설정하는 데 도움을 준다.
$HOME 환경 변수
1) user로 로그인할 경우 : $HOME > /home/user
2) admin로 로그인할 경우 : $HOME > /home/admin
3) ubuntu로 로그인할 경우 : $HOME > /home/ubuntu
- 환경변수 확인은 evn 명령어로 확인 가능하다
- 환경변수를 사용하면 쉘 스크립트 실행시 값이 변하므로 환경에 맞는 처리가 가능해진다
명령어 치환
-쉘이나 쉘 스크립트에서 ${변수명} , `변수명`으로 적으면 명령어열 실행 결과의 문자열로 치환된다
-명령어 치환에서 파이프 라인이나 변수 등도 사용 가능
예시. 날짜 형식
$ date +%y%m%d
231111
$ date +%Y-%m-%d
2023-11-11
$ date +%Yy%mm%dd%Hh
2023y11m11d22h
쉘 스크립에서 위의 날짜 형식과 명령어 치환을 적용하면
#!/bin/bash
mv result.txt result-$(date +%Y-%m-%d).txt // 현재 2023-11-11로 치환
- result-2023-11-11.txt로 파일명 변경된다
다른 예시.
path=/data/2023-11-11/files/file.txt
parent=$(dirname $path) -- /data/2023-11-11/files
grandparent=$(driname $parent) -- /data/2023-11-11
결과 /data/2023-11-11
명령어 치환을 겹쳐 아래와 같이 한줄로 표현 가능하다
grandparent=$(dirname $(dirname $path))
17장. 로그 파일에서 필요한 줄만 뽑고 싶어 ( cut )
cut 명령어
- 파이프로 넘어온 내용의 각 줄마다 필요한 부분만 잘라내서 돌려준다
- 주요 옵션으로 -d (--delimiter, "구분자")와 -f (--fields, 추출할 위치)
사용 예시
-d : 구분자로 / 지정
-f : 4번째 위치에 있는 문자열 지정
Java String 클래스의 split()과 배열 인덱스로 조회하는 느낌이 난다
파이프 라인을 거쳐 한번 더 cut을 하여 문자열 처리 하는 방식도 사용하는 것으로 보인다
참고. tac 명령어
cat의 반대로, 마지막줄부터 출력을 시작해서 파일 첫 줄까지 출력하고 끝나게 된다
18장. 같은 내용의 줄을 세어보고 싶어 (sort와 uniq)
중복 제거
- uniq 명령어의 경우 "중복을 제거하는 명령어" 이지만 "이어진 중복"만을 제거한다
- 즉, 미리 sort 명령어를 수행해두면 중복을 제대로 제거할 수 있다
카운트 세기
uniq 명령어에서 -c (--count) 옵션을 사용하게 되면, 실행 결과에서 각 내용이 몇번 등장했는지 출력해준다
*참고. 직접 해본 url 카운트 수 세기
톰캣 catalina.out 로그 파일에서 아래와 같은 url의 통계를 구해보았다
13:13:54.897 [DEBUG] [localhost-startStop-1] [c.web.mvc.AnnotationHandlerMapping] - register handlerExecution : url is /users/loginForm, method is public core.web.view.ModelAndView next.controller.user.UserController.loginForm(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) throws java.lang.Exception
$ cat catalina.out | grep -E '(register handlerExecution)' | cut -d ' ' -f 11 | cut -d ',' -f 1 | sort | uniq -c
16 /
16 /api/qna/addAnswer
16 /api/qna/deleteAnswer
16 /api/qna/deleteQuestion
16 /api/qna/list
16 /qna/create
16 /qna/delete
16 /qna/form
16 /qna/show
16 /qna/update
16 /qna/updateForm
16 /users
16 /users/create
16 /users/form
16 /users/login
16 /users/loginForm
16 /users/logout
16 /users/profile
16 /users/update
16 /users/updateForm
- uniq -c 할 경우 집계가 오른쪽 정렬되어 있는데, 이는 단순 정렬 용이하게 함이 위함이다
- cut의 기본 구분자가 탭(\t)으로 되어 있다
- sort는 기본적으로 오름차순 정렬된다 (-r 옵션을 추가할 경우 내림차순 정렬됨)
이외 tail 과 head 명령어를 파이프 통해 원하는 수만 큼 라인을 출력 가능하다
19장. CSV 파일을 열의 내용에 따라 정렬하고 싶어 (sort 와 리다이렉트)
cut에서 원하는 열만 선택하기
csv 파일은 콤마(,)로 구분되어져 있어 아래와 같이 구분자 지정 후 원하는 열을 선택한다
$ cut --delimeter ',' --fields 1,3,4,6
$ cut -d ',' -f 1-3
sort에서 구분자로 나눠 지정하여 정렬하기
$ sort --filed-seprarator ',' --key 3
$ sort -t ',' -k 3
--filed-separator 또는 -t 옵션으로 구분자를 지정
--key또는 -k옵션으로 열 번호를 지정하면 해당 열 기준으로 재정렬함
--number 또는 -n옵션을 지정하면 숫자로 해석해서 값의 크기로 재정렬함
--ignore-leading-balnks 또는 -b옵션을 사용하면 오른쪽 줄맞춤을 위해 넣은 스페이스를 무시하고 문자열 정렬할 수 있음
리다이렉트
명령어 실행 결과를 저장하는 기본 테크닉
- > : create, 파이프 라인으로 넘어 온 결과를 새로운 파일로 만들어 씀 (기존 파일 날라감)
- >> : append, 기존 파일에 맨 마지막 라인부터 내용 추가한다
$ echo 'hello world' > test.txt
$ cat test.txt
hello world
20장. 명령줄 지정으로 작업 내용을 바꾸고 싶어 (명령줄 인수)
명령어 라인에서 스크립트 이름 뒤에 인수 지정해서 실행할 경우
쉘 스크립트 내부에서는 지금 처럼 실행시 지정한 인수 값을 $1같은 변수로 참조하여 사용할 수 있다
그리고 쉘 스크립트 내부에서 직접 옵션값을 정의하고 변수로 참조할 수 있게 만들 수도 있다
#!/bin/bash
#b:n:p:o:을 옵션명으로 사용하겠다는 의미, 이외는 문법적인 부분인듯하다
while getopts b:n:p:o: OPT
do
case $OPT in
#옵션명) 변수명="$OPTARG"
b) base="$OPTARG";;
n) next="$OPTARG";;
p) prev="$OPTARG";;
o) output="$OPTARG";;
esac
done
*쉘 스크립트 내부에서는 base, next, prev, output 변수 사용하면 된다
호출 예시
$ ./script.sh -b base.log -n next.log -p prev.log -o output.log
21장. 조건에 따라 처리 흐름을 바꾸고 싶어 ( if , 조건분기)
예시
#!/bin/bash
if [ $# = 2 ]
then
echo "hello world"
fi
$# : 스크립트에 지정한 인수 개수를 의미하는 특수한 변수
[ : /usr/bin/[ 에 존재하는 명령어이다, 대괄호 [ , ] 사이에는 공백이 꼭 있어야 함
조건문 문법
if [ 조건 ]
then
조건을 만족하면 실행하는 내용
elif [ 조건 ]
then
elif 조건을 만족하면 실행하는 내용
else
조건을 만족하지 않으면 실행하는 내용
fi
참고. shell basic operator (비교, 논리, 산술 연산자)
https://www.tutorialspoint.com/unix/unix-basic-operators.htm
22장. 명령어 이상 종료에 대응하고 싶어 ($?, 종료상태)
$?
- $? 으로 직전에 실행한 명령어 종료 상태를 참조 가능
- $? 값은 명령어가 정상 종료하면 0, 이상 종료하면 0이외의 값이 됨
- exit에 인수로 숫자를 지정하면 쉘 스크립트의 종료 상태가 됨
특별히 에러 종류를 구별할 필요가 없으면 exit 1을 지정하는 보통 (0이외 무엇을 지정해도 됨, 범위 1 ~ 255 )
- if로 종료 상태를 참조하면 명령어가 정상 종료했는지에 따라 조건 분기가 가능
#!/bin/bash
if [ $? != 0 ]; then exit; fi
23장. 같은 처리를 반복해서 실행하고 싶어 (for)
아래와 같이 반복되는 작업이 있을 경우 for loop 통해서 처리 가능하다
$ ./execute.sh a.log
$ ./execute.sh b.log
$ ./execute.sh c.log
$ ./execute.sh d.log
for-loop 예시
#!/bin/bash
# a ~ b.log 파일까지 순차적으로 fileName에 할당
for fileName in a.log b.log c.log b.log
do
./execute.sh $fileName
done;
아래와 같이 처리대상을 명령어 조건으로 추상화할 수 있다
#!/bin/bash
# /tmp/log 폴더에 있는 *.log 파일 중 error.log 제외한 결과를 fileName에 순차 할당
for fileName in `cd /tmp/log; ls *.log | grep -v error.log`
do
./execute.sh $fileName
done;
참고. 한줄로 for문, if문 작성 방법
줄바꿈 대신 ; (세미콜론)을 쓰면 한 줄로 만들어서 일반 명령어처럼 실행가능하다
# for
$ for file in data log scripts; do echo $file; done
# if
$ if [ $1 = "" ]; then echo $1; fi
24장. 공통 처리를 계속 재사용하고 싶어 (쉘 함수)
함수는 아래와 같이 정의할 수 있다
#!/bin/bash
hello() {
echo "hello"
}
hello
-어떤 처리를 하나로 묶어서 함수로 정의 가능
-정의한 함수는 같은 스크립트 안에서 원하는 곳에서 몇번이고 호출 가능
함수 호출할 때 일반 명령어나 쉘 스크립트처럼 인수를 지점하면 함수 안에서 $1, $2, ... 라는 변수로 인수 값을 참조 할 수 있다
#!/bin/bash
hello() {
echo "hello $1"
}
hello world
hello jw
함수의 종료 상태
-스크립트와 마찬가지로 0 또는 0이외의 값을 가진다
-단 함수의 종료 상태를 명시적으로 지정할 때는 exit가 아닌 return을 사용해야 하는 점에서 다르다
-함수의 return 의 경우 그 함수 실행만 중단되고 함수 호출 부분으로 돌아가는데, exit는 스크립트 자체 처리까지 도중에 중단한다
#!/bin/bash
# 조건 분기
if [ $1 = "" ]
then
echo "인수가 필요함"
exit 1
fi
# 함수
report() {
if [ $1 = "" ]
then
echo "인수가 필요함"
return 1
fi
}
*이때 조건분기의 $1은 스크립트의 인수이고, 함수의 $1은 함수의 인수이다. 즉 쉘에서 명령어 라인으로 실행시 전달하면 스크립트 인수이고, 쉘 스크립트 안에서 함수 실행시 전달하면 함수 인수 (report arg1)
p190 함수를 활용한 쉘 스크립트 예시
- 쉘 스크립트는 기본적으로 실행하고 싶은 명령어를 실행 순서대로 작성하지만, 함수를 사용한다면 실행 순서를 신경쓰지 않고 중요한 부분부터 스크립트를 작성할 수 있다
- main() 함수가 최상단에 있어 today()가 정의되어 있지 않더라도, 제일 하단에서 main을 실행하므로 최초 정의 시점에는 오류가 발생하지 않음
- 중요한 처리를 main 함수로 미리 정의해두고 마지막에 그걸 호출하는게 보통이다
#!/bin/bash
main() {
report marketing.log mail-$(today).csv /shared/marketing/reports
report system.log $(today).csv /shared/system/mail-reports
report develop.log $(today).csv /shared/develop/reports/mail
}
report() {
source=$1
report=$2
outdir=$3
./analyze_mail_log.sh $source $report
mkdir -p $outdir
mv /tmp/${report} ${outdir}/
echo "$source 처리 완료"
}
today() {
date +%Y-%m-%d
}
main
실무에서 일하다보면 사수가 없어 "누군가 알려주는 사람이 있었으면 좋겠다"는 생각을 한적이 있는데, 신입인 주인공에게 상사가 친절하게 기초부터 설명한다는 점이 인상깊은 책이었습니다.
서버 셋팅은 할 줄 알지만, 이 책을 보고 shell script 문법에서 모르는 부분이 있었다는 걸 깨닫고 기초가 부족함을 느꼈었다
개발 커뮤니티에서 역시 추천하는 이유가 있는 책이었다
'독서 > 📚' 카테고리의 다른 글
[도서] 이것이 취업을 위한 코딩테스트다 (with 파이썬) 후기 (0) | 2025.01.10 |
---|---|
[개발도서]프로그래머 열정을 말하다 (채드 파울러) (2) | 2024.05.02 |
[Next Step] 12장 확장성 있는 DI 프레임워크로 개선 (0) | 2023.11.23 |
[Next Step] 11장 의존관계 주입(DI)을 통합 테스트 하기 쉬운 코드 만들기 (0) | 2023.11.21 |
[Next Step] 10장 새로운 MVC 프레임워크 구현을 통한 점진적 개선 (2) | 2023.11.20 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!