LabHub

리눅스 기초 · 텍스트 처리 파이프라인 · 이론

파이프는 작은 프로그램을 문장으로 잇는다

LabHub 에서 이어서 보기

한 줄 요약

grep 은 고르고, sed 는 고치고, awk 는 센다. 이 세 도구를 파이프로 이으면 로그 수십만 줄에서 답을 뽑는 데 다섯 줄이면 충분하다.

왜 이게 필요했나

장애 보고를 받았다. "오후 3시부터 응답이 느립니다." 로그는 40만 줄이고, 편집기로 열면 그 자체가 몇 초 걸린다. 여기서 필요한 것은 로그 뷰어가 아니라 질문을 명령으로 옮기는 능력이다.

세 질문이 전부 같은 모양이다. 그래서 관용구를 하나만 외우면 된다.

... | sort | uniq -c | sort -rn | head

uniq -c인접한 중복만 세기 때문에 앞에 sort가 반드시 필요하고, 뒤의 sort -rn은 개수 기준 내림차순이다. 이 네 토막이 "무엇이 가장 많은가"라는 질문의 표준 답이다.

어떻게 동작하나

도구 선택 기준은 단순하다. 줄을 고르기만 하면 grep, 줄을 고치면 sed, 필드를 다루거나 계산하면 awk 다. 필요 이상으로 강한 도구를 쓰면 느려지고 읽기 어려워진다.

파이프의 정체도 알아 둘 것. 파이프로 이어진 각 명령은 별도의 프로세스에서 동시에 실행되며, 앞의 stdout 이 뒤의 stdin 으로 연결된다. 여기서 두 가지 성질이 따라 나온다.

1. 큰 파일도 전부 메모리에 올리지 않고 흘려보내며 처리한다. 그래서 40만 줄도 빠르다.
2. 파이프 안에서 바꾼 변수는 바깥에 남지 않는다. 서브셸이기 때문이다.

그리고 파이프라인의 종료 코드는 기본적으로 맨 마지막 명령의 것이다. curl ... | jq ... | wc -l 에서 curl 이 실패해도 wc 가 0을 내놓으면 전체는 성공으로 보인다. 스크립트에서 이 함정을 막는 장치가 set -o pipefail 이고, 다음 코스에서 자세히 다룬다.

성능 안티패턴 몇 가지는 지금 고쳐 두는 게 좋다.

| 이렇게 쓰지 말고 | 이렇게 |
| --- | --- |
| cat f | grep p | grep p f |
| sort | uniq | sort -u |
| cat f | wc -l | wc -l < f |
| echo "$s" | cut -d. -f1 | ${s%%.*} |

현장에서 만나는 모습

첫째, 상태코드 집계. awk '$9 ~ /^5[0-9][0-9]$/ {print $7}' access.log | sort | uniq -c | sort -rn | head -10 한 줄이면 5xx 를 가장 많이 낸 경로 열 개가 나온다. 대시보드를 열기 전에 이걸 먼저 친다.

둘째, 비율 계산은 awk 로. 개수만으로는 판단이 안 될 때가 많다. awk '{t++; if ($5 != 200) e++} END {printf "%.1f\n", e*100/t}' 처럼 END 블록에서 한 번에 계산하면 파일을 두 번 읽지 않아도 된다.

셋째, 로그를 처음부터 읽지 말 것. 장애 시각 앞뒤 5분만 잘라 내는 것이 첫 동작이다. 40만 줄 전체를 훑는 습관은 시간을 잡아먹을 뿐 아니라, 이미 I/O 가 포화된 디스크에서는 진단 자체가 장애를 키운다.

다음 실습에서 할 것

/opt/lab/data/app.log 를 재료로 오류 건수, 최다 요청 IP, 상태코드별 집계, 상위 경로, 오류율을 차례로 뽑고, 마지막에는 그 결과를 세 줄짜리 요약 리포트로 묶는다.