Apache 접근 로그 · 오류 로그 칸별 풀이
Apache access_log 나 error_log 를 여기에 놓으면 상태 코드, 오류 경로, 상위 클라이언트, 그리고 형식에 %D 가 있으면 응답 시간 분위수가 나옵니다. 로그는 브라우저 안에만 있습니다.
mod_log_config 의 common · combined 형식, 응답 시간을 남기는 법, 2.4 오류 로그 한 줄 읽는 법, 서버에서 쓸 한 줄 명령을 정리했습니다.
common 과 combined
mod_log_config 문서에 나오는 형식 문자열입니다. 셋째 줄은 combined 끝에 요청 처리 시간(마이크로초) %D 를 붙인 것입니다.
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %D" combined_time
CustomLog logs/access_log combined_timecombined_time 으로 남긴 접근 로그 한 줄입니다.
198.51.100.7 - - [18/Oct/2026:10:02:31 +0000] "GET /report.php?id=8 HTTP/1.1" 500 612 "-" "Mozilla/5.0" 30001544| awk 칸 | 지시자 | 예시 값 | 뜻 |
|---|---|---|---|
| $1 | %h | 198.51.100.7 | 원격 호스트입니다. HostnameLookups 기본값이 Off 라 IP 주소가 찍히고, 켜면 호스트 이름이 찍힙니다. |
| $2 | %l | - | identd 의 원격 로그인 이름입니다. mod_ident 를 싣고 IdentityCheck 를 켜지 않으면 대시입니다. |
| $3 | %u | - | 인증된 사용자입니다. 상태가 401 이면 믿을 수 없는 값일 수 있습니다. |
| $4 $5 | %t | [18/Oct/2026:10:02:31 +0000] | 요청을 받은 시각과 GMT 와의 차이입니다. |
| $6 $7 $8 | \"%r\" | "GET /report.php?id=8 HTTP/1.1" | 요청의 첫 줄입니다. |
| $9 | %>s | 500 | 최종 상태입니다. %s 는 내부 리다이렉트된 요청이면 원래 요청의 상태를 남깁니다. |
| $10 | %b | 612 | 헤더를 뺀 응답 크기입니다. CLF 방식이라 보낸 바이트가 없으면 0 대신 대시입니다. |
| $11 | \"%{Referer}i\" | "-" | Referer 요청 헤더(combined 만)입니다. |
| $12 … | \"%{User-agent}i\" | "Mozilla/5.0" | User-Agent 헤더(combined 만)입니다. 공백이 있으므로 큰따옴표로 잘라야 통째로 얻습니다. |
| 마지막 | %D | 30001544 | 요청 처리에 걸린 시간, 마이크로초입니다. 30001544 µs 는 30.0초입니다. |
응답 시간: %D · %T · %{UNIT}T
| 지시자 | 단위 | 참고 |
|---|---|---|
%D | 마이크로초 | 분위수를 볼 때 쓸 값입니다. |
%T | 초 | 정수 초라서 1초 미만은 모두 0 으로 찍힙니다. 30초 시간 초과를 찾는 데는 되지만 빠른 API 의 p99 에는 쓸 수 없습니다. |
%{ms}T | 밀리초 | %{us}T(%D 와 같음), %{s}T(%T 와 같음)도 있습니다. 2.4.13 부터 됩니다. |
%I / %O | 바이트 | 헤더를 포함해 받은 · 보낸 바이트입니다. mod_logio 가 필요합니다. |
시간은 User-Agent 뒤, 형식 맨 끝에 두십시오. combined 칸이 모두 제자리에 있고 $NF 가 늘 처리 시간이 됩니다. 보드는 끝의 숫자를 알아보고 %D 또는 %T 로 읽습니다.
이 값은 요청을 처리하는 데 걸린 시간이므로, 프록시나 FastCGI 로 넘긴 요청이면 백엔드가 쓴 시간까지 들어갑니다. PHP 나 프록시 경로에서 %D 가 크면 같은 초의 오류 로그를 다음으로 보십시오.
2.4 오류 로그
오류 로그 모양은 ErrorLogFormat 이 정합니다. 기본값이면 한 줄이 다음과 같습니다.
[Sun Oct 18 10:04:30.654321 2026] [core:error] [pid 4123:tid 140230300] [client 198.51.100.7:41900] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error.| 부분 | 예시 값 | 뜻 |
|---|---|---|
| 시각 | [Sun Oct 18 10:04:30.654321 2026] | 마이크로초까지의 날짜 · 시각입니다. |
| 모듈:수준 | [core:error] | 메시지를 쓴 모듈과 심각도입니다. |
| 프로세스 | [pid 4123:tid 140230300] | 프로세스 번호와, 스레드형 MPM 이면 스레드 번호입니다. |
| 클라이언트 | [client 198.51.100.7:41900] | 요청에 관한 메시지일 때 클라이언트 주소와 포트입니다. |
| 메시지 | AH00124: Request exceeded … | 메시지이며 대개 그것을 가리키는 AH 코드로 시작합니다. |
모듈:수준 별, AH 코드별로 세는 것이 무엇이 달라졌는지 보는 가장 빠른 길입니다. 새 AH 코드 하나가 수천 번 찍혔다면 대개 그것이 장애입니다.
Apache 2.2 오류 로그에는 모듈 · pid 부분이 없습니다([시각] [error] [client …] 메시지). 보드는 둘 다 읽습니다.
Apache 로그에서 보드가 보여 주는 것
- 상태 코드, 오류가 나는 곳, 상위 경로, 상위 클라이언트 IP, 누가 부르나, 경로별 전송량.
%D나%T가 있으면 지연 분포와 느린 경로.- 끌어서 고르는 분 단위 시간축 — 모든 카드와 원문 줄이 선택을 따릅니다.
- 스캐너 탐침 —
wp-login.php·.env·.git/같은 경로를 찾는 요청. - 오류 로그: 모듈:수준별 줄 수, AH 코드, 클라이언트 주소, 시간축.
Apache 로그용 한 줄 명령
%D 를 덧붙인 combined 표본과 2.4 오류 로그로 실행해 확인했습니다. 파일 이름은 RHEL 계열 기본값(access_log · error_log)이며, Debian · Ubuntu 는 access.log · error.log 입니다.
상태 코드 분포
awk '{print $9}' access_log | sort | uniq -c | sort -rn요청이 가장 많은 클라이언트
cut -d' ' -f1 access_log | sort | uniq -c | sort -rn | head4xx 를 받는 경로와 코드
awk '$9 ~ /^4/ {print $9, $7}' access_log | sort | uniq -c | sort -rn | head%D 로 본 가장 느린 요청 5개(밀리초)
awk '{printf "%.1f ms %s\n", $NF/1000, $7}' access_log | sort -rn | head -5%D 의 p95(최근접 순위)
awk '{print $NF}' access_log | sort -n | awk '{a[NR]=$1} END {i=int(NR*0.95); if (i<NR*0.95) i++; printf "%.1f ms\n", a[i]/1000}'경로별 평균 시간과 요청 수
awk '{s[$7]+=$NF; n[$7]++} END {for (p in s) printf "%.1f ms %d %s\n", s[p]/n[p]/1000, n[p], p}' access_log | sort -rn분당 요청 수
cut -d[ -f2 access_log | cut -d: -f1-3 | uniq -c응답 바이트 합계(%b 는 0 대신 대시를 남기므로 건너뜀)
awk '$10 != "-" {s+=$10} END {printf "%.1f KiB\n", s/1024}' access_log오류 로그: 모듈:수준별 줄 수
grep -oE '^\[[^]]+\] \[[a-z_0-9]+:[a-z0-9]+\]' error_log | awk '{print $NF}' | sort | uniq -c | sort -rn오류 로그: 자주 나온 AH 코드
grep -oE 'AH[0-9]{5}' error_log | sort | uniq -c | sort -rn | head오류 로그: 오류를 일으킨 클라이언트 주소
grep -oE '\[client [0-9a-f.:]+' error_log | awk '{print $2}' | sed -E 's/:[0-9]+$//' | sort | uniq -c | sort -rn | head
자주 묻는 질문
%D 와 %T 는 무엇이 다른가요?
%D 는 요청 처리 시간을 마이크로초로, %T 는 같은 시간을 정수 초로 남깁니다. 분위수를 보려면 %D, 또는 2.4.13 이상이면 %{ms}T 를 쓰십시오.
%b 에 대시가 찍히는 이유는?
%b 는 Common Log Format 관례를 따라 본문을 한 바이트도 보내지 않으면 0 대신 대시를 씁니다(예: 304). %B 는 0 을 씁니다.
%s 와 %>s 는 무엇이 다른가요?
내부 리다이렉트된 요청에서 %s 는 원래 요청의 상태, %>s 는 최종 상태입니다. 접근 로그에는 보통 %>s 를 씁니다.
첫 칸이 IP 가 아니라 호스트 이름인 이유는?
HostnameLookups 가 켜져 있습니다. 기본은 꺼짐이며, 켜면 요청마다 역방향 DNS 조회를 해서 느리고 칸을 묶기도 어려워집니다.
Apache 로그는 어디에 있나요?
빌드와 배포판마다 다릅니다. RHEL 계열은 /var/log/httpd/, Debian · Ubuntu 는 /var/log/apache2/ 가 흔합니다. 정답은 설정의 CustomLog · ErrorLog 지시자입니다.
Apache 2.2 오류 로그도 읽나요?
읽습니다. 모듈 · pid 부분이 없는 옛 모양도 알아봅니다.
%v 처럼 가상 호스트를 넣은 형식은요?
%h 앞에 칸을 넣는 형식은 모든 위치를 한 칸씩 밉니다. 형식 탭에서 칸 역할을 한 번 표시하고 레시피로 저장하십시오.