두 개의 웹 서버가 있고 요청 수를 기준으로 정렬된 상위 10개 IP를 알고 싶습니다.
웹 서버는 Apache 기반이므로 access.log 파일을 살펴봐야 합니다.
문제는 이런 파일들이 대용량이기 때문에 꼭 로컬로 스트리밍하고 싶지 않은데 스트리밍에서 할 수 있는 방법이 없을지 궁금합니다. 실제로 SSH를 통해 이 컴퓨터에 액세스할 수 있습니다.
내 생각에 한 가지 방법은 다음과 같이 실행하는 것입니다.
awk "{ print $1 }" access.log | sort | uniq -c | sort -n | tail
두 컴퓨터 모두에서 로컬로 결과를 결합하지만 이는 분명히 잘못된 것입니다.
답변1
개념적으로는 파일 크기에만 관심이 있으므로 필요한 것은 다음과 같습니다.
{
ssh server2 cat /path/to/access.log
cat /local/path/to/access.log
} | awk '{print $1}' | sort | uniq -c | sort -n | tail
그러나 속도를 향상시키기 위해 할 수 있는 일이 많이 있습니다.
대역폭을 줄이기 위해 먼저 네트워크를 통해 IP 주소만 보냅니다.
{
ssh server2 awk '{print $1}' /path/to/access.log
cat /local/path/to/access.log
} | awk '{print $1}' | sort | uniq -c | sort -n | tail
둘째, awk의 해싱을 활용하여 정렬이 필요하지 않도록 합니다. 이는 n*lg(n) 차수를 n 차수로 대체합니다. 이는 연관 배열을 사용하여 seen
각 IP 주소가 표시된 횟수를 계산하고 마지막에 횟수와 주소를 인쇄합니다.
{
ssh server2 awk '{print $1}' /path/to/access.log
cat /local/path/to/access.log
} | awk '{seen[$1]++} END {for (i in seen){print seen[i],i}}' | sort -n | tail
세 번째 역정렬은 다시 흘러야 하는 데이터의 양을 줄입니다.
{
ssh server2 awk '{print $1}' /path/to/access.log
cat /local/path/to/access.log
} | awk '{seen[$1]++} END {for (i in seen){print seen[i],i}}' | sort -rn | head
데이터에 따라 원격 웹 서버에서 데이터를 전처리하는 것이 합리적일 수 있습니다. ( 입력을 저장하기 seen
위해 배열 이름이 변경되었습니다 s
). 여기로 전송되는 데이터는 개수와 주소 쌍입니다. 그런 다음 세 번째 awk 프로세스에서 로컬로 함께 추가합니다.
{
ssh server2 awk '{s[$1]++}END{for (i in s){print s[i],i}}' /path/to/access.log
awk '{s[$1]++}END{for (i in s){print s[i],i}}' /local/path/to/access.log
} | awk '{s[$2]+=$1}END{for (i in s){print s[i],i}}' | sort -rn | head
물론 테스트되지 않았습니다.