로그를 볼 때 유용한 shell 명령어들

서버 개발을 하다보면, 로그를 밥먹듯이 보게 된다. 로그는 디버깅을 하는데 이용되기도 하지만, 때로는 원하는 통계와 데이터를 얻기 위해 사용되기도 한다.
이 글은 후자의 경우, 내가 자주 겪었던 문제와 이를 해결하기 위해 사용했던 방법들을 정리하기 위해 작성하였다.

예제에 사용된 access_log는, 운영하고 있는 블로그의 실제 access.log 파일을 사용하였습니다.

특정 단어가 포함된 줄 뽑아내기

Mac OS를 사용하고 있는 유저의 요청 로그만을 뽑고 싶다고 가정해보자.
Mac OS를 사용하고 있는 유저의 로그에는 'Macintosh; Intel Mac OS X' 이라는 단어가 존재한다는 공통점을 이용하면, grep 으로 쉽게 뽑아낼 수 있다.

$ grep 'Macintosh; Intel Mac OS X' access.log

만약 총 몇 개의 요청이 있었는지 카운트하고 싶다면, wc -l 명령어를 파이프라인으로 연결하면 된다.

$ grep 'Macintosh; Intel Mac OS X' access.log | wc -l
32  

특정 위치의 단어 뽑아내기

이번에는 로그에서 GET 으로 들어온 요청의 경로(PATH)만을 뽑아내고 싶다고 가정해보자.
일단 GET 으로 들어온 요청은 앞에서와 동일하게 grep 만으로 쉽게 뽑아낼 수 있다.

$ grep 'GET /' access.log

문제는 경로를 뽑아내는 것인데, 로그를 자세히 보면 각 줄을 공백으로 구분했을 때 7번째 구성요소가 항상 경로인 점을 발견할 수 있다. 이러한 규칙을 이용하면 cut 명령어로 뽑아낼 수 있다.

$ grep 'GET /' access.log | cut -d " " -f 7
/
/2019/07/15/java-heap-dump-analysis/
/robots.txt
...

만약 각 경로별로 카운트를 하고 싶다면, sortuniq 명령어를 함께 이용하면 된다.

$ grep 'GET /' access.log | cut -d " " -f 7 | sort | uniq -c
73 /  
 3 /2016/09/25/decorator-class/
 1 /2016/09/25/decorator-function/
 1 /2016/10/05/ci-github-slack
 1 /2016/10/05/ci-github-slack/
...

추가로, 가장 많이 카운트된 순서대로 위에서부터 출력하고 싶다면, sort 를 한번 더 사용하면 된다.

$ grep 'GET /' access.log | cut -d " " -f 7 | sort | uniq -c | sort -nr
73 /  
40 /assets/js/jquery.fitvids.js?v=6ea3fea03b  
40 /assets/js/index.js?v=6ea3fea03b  
39 /assets/css/screen.css?v=6ea3fea03b  
35 /favicon.ico  
...

특정 패턴에 해당하는 단어 뽑아내기

이번에는 GET /favicon.ico 으로 들어온 요청에서 HH(시):MM(분):SS(초) +0000 부분만을 깔끔하게 뽑아내고 싶다고 가정해보자.
일단 앞서 배운 것들을 이용해 [05/Nov/2019:HH:MM:SS +0000] 라고 적힌 부분만을 뽑아낼 수 있다.

$ grep 'GET /favicon.ico' access.log | cut -d " " -f 4 -f 5
[05/Nov/2019:19:33:45 +0000]
[05/Nov/2019:19:34:40 +0000]
[05/Nov/2019:20:00:47 +0000]
...

먼저 앞의 [05/Nov/2019: 부분을 제거해보자. 이때 awk 명령어를 이용하면 이러한 처리를 쉽게 할 수 있다.

$ grep 'GET /favicon.ico' access.log | cut -d " " -f 4 -f 5 | awk -F '0[5-6]/Nov/2019:' '{print $2}'
19:33:45 +0000]  
19:34:40 +0000]  
20:00:47 +0000]  
...

유사한 방법으로 끝에 붙어있는 ] 도 제거할 수 있다.

$ grep 'GET /favicon.ico' access.log | cut -d " " -f 4 -f 5 | awk -F '0[5-6]/Nov/2019:' '{print $2}' | awk -F ']' '{print $1}'
19:33:45 +0000  
19:34:40 +0000  
20:00:47 +0000  
...

참고