- 세상의 모든 계산기 자유(질문) 게시판 일반 ()
(Nginx) "웹 크롤러 request 순위 확인" 스크립트 (우분투)
#!/bin/bash # monip.sh # Nginx access 로그에서 상위 25개 IP를 분석하여 # - Bot (Crawler)인 경우: User-Agent 문자열로 Bot 종류를 추출 # - User인 경우: whois 명령으로 Organization Name 조회 # 그리고 IP별 국가 정보(geoiplookup)를 추가하여 출력함 LOG_FILE="/var/log/nginx/access.log" if [ ! -f "$LOG_FILE" ]; then echo "로그 파일이 존재하지 않습니다: $LOG_FILE" exit 1 fi awk ' # Bot의 종류를 판별하는 함수 function get_bot_type(ua, ua_lower) { ua_lower = tolower(ua) if(ua_lower ~ /googlebot/) return "Googlebot" if(ua_lower ~ /bingbot/) return "Bingbot" if(ua_lower ~ /slurp/) return "Yahoo Slurp" if(ua_lower ~ /duckduckbot/) return "DuckDuckBot" if(ua_lower ~ /baiduspider/) return "Baiduspider" if(ua_lower ~ /yandex/) return "YandexBot" return "Unknown Bot" } # User-Agent 문자열을 바탕으로 사용자 종류를 판별 function classify_user_agent(ua) { if(ua == "" || ua == "-") return "알 수 없음" ua_lower = tolower(ua) if(ua_lower ~ /bot|crawl|spider|slurp|mediapartners/) return "Bot (Crawler)" return "User" } # geoiplookup 명령을 사용하여 IP의 국가 정보를 가져오는 함수 function get_country(ip, cmd, result, arr, country) { cmd = "geoiplookup " ip " 2>/dev/null" if ((cmd | getline result) > 0) { # 예: "GeoIP Country Edition: US, United States" split(result, arr, ":") if(length(arr) > 1) { country = arr[2] gsub(/^[ \t]+|[ \t]+$/, "", country) } else { country = "Unknown" } } else { country = "조회 실패" } close(cmd) return country } { # Combined log format 예제: # 127.0.0.1 - - [14/Feb/2025:12:00:00 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 ..." regex = "([^ ]*) - ([^ ]*) \\[([^\\]]*)\\] \"([^\"]*)\" ([^ ]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\"" if(match($0, regex, arr)) { ip = arr[1] referer = arr[7] ua_str = arr[8] count[ip]++ # IP별 요청 횟수 집계 ua_stats[ip, ua_str]++ # IP별 User-Agent 빈도 집계 ref_stats[ip, referer]++ # (참고용) 리퍼러 집계 } } END { # gawk의 asorti() 함수로 요청 횟수 기준 내림차순 정렬 n = asorti(count, sorted, "@val_num_desc") # 헤더 출력 (순서: 순위 | IP | 국가 | Requests | 사용자 종류 | 기타정보) printf("| %-2s | %-15s | %-18s | %-10s | %-17s | %-21s |\n", "순위", "IP", "국가", "Requests", "사용자 종류", "기타정보") print("|------|-----------------|----------------------|------------|------------------------|-------------------------|") limit = (n < 25 ? n : 25) for(i = 1; i <= limit; i++){ ip = sorted[i] req_count = count[ip] # 해당 IP의 가장 많이 등장한 User-Agent 선택 max_ua = "" max_ua_count = 0 for(key in ua_stats) { split(key, parts, SUBSEP) if(parts[1] == ip) { if(ua_stats[key] > max_ua_count) { max_ua_count = ua_stats[key] max_ua = parts[2] } } } user_type = classify_user_agent(max_ua) extra = "" if(user_type == "User") { # User인 경우: whois 명령으로 Organization Name 조회 cmd = "whois " ip " 2>/dev/null | grep -i -m 1 \"orgname:\"" org = "" if((cmd | getline org) > 0) { sub(/^[ \t]+/, "", org) split(org, a, ":") if(length(a) > 1) { org = a[2] gsub(/^[ \t]+/, "", org) } } else { org = "조회 실패" } close(cmd) extra = org } else if(user_type == "Bot (Crawler)") { extra = get_bot_type(max_ua) } else { extra = "없음" } # 각 IP의 국가 정보 추가 country = get_country(ip) printf("| %-4d | %-15s | %-20s | %-10d | %-22s | %-25s |\n", i, ip, country, req_count, user_type, extra) } } ' "$LOG_FILE"
사용 방법
- 스크립트를 파일에 저장 후 실행 권한 부여:
chmod +x monip.sh
- 스크립트 실행 (필요한 경우 sudo로):
sudo ./monip.sh
결과
세상의모든계산기 님의 최근 댓글
approx(참 해) 값이 이상하게 튀는 것 같아서 wolfram alpha 로 구해보려고 했는데 수식 길이가 너무 길다고 거부하는 바람에 AI를 이용해 (python 으로) 구해본 것입니다. 참 해가 계산 과정이 너무 길다보니 nspire 계산기에서는 오차가 누적되어 오히려 numeric 한 접근보다도 더 큰 오차가 발생한 듯 하고, 그래서 적절한 해의 x 구간을 벗어나버린 듯 합니다. 2025 10.21 그래프로 확인 그래프 함수로 지정하고, 매우 좁은 구간으로 그래프를 확대해 보면 불연속적인 그래프 모습이 확인됩니다. 이것은 한계 digits(15자리) 이상을 처리하지 못하기 때문일 것이구요. 다만 특이한 점은, 그래프상으로 교점에 해당하는 구간이 73.049507058477≤x≤73.049507058484 사이로 나오는데 -> 이 구간은 'solve에서 여러 방법으로 직접 구해진 해들'은 포함되는 구간입니다. -> 하지만, '참값인 해를 계산기로 구한 appprox 값 x=73.049507058547'은 포함되지 않는 구간입니다. 2025 10.21 tns 파일 첨부 sol_num_vs_exact.tns 2025 10.21 검증하면 1번 식을 x에 대해 정리하고, → 그 x 값을 2번 식에 대입해 넣으면 → 그 결과로 x는 사라지고 y에 대한 식이 되니, y에 대해 정리하면 참값 y를 얻음. 얻은 y의 참값을 처음 x에 대해 정리한 1번식에 대입하면 참 값 x를 얻음. 구해진 참값의 근사값을 구하면 x=73.049507058547 and y=23.747548955927 참 값을 approx() 로 변환한 근사값은 원래 방정식 모두를 만족할 수 없지만, linsolve() 로 찾은 근사값과, AI로 참 값을 근사변환한 값은 원래 방정식 모두를 만족할 수 있습니다. 2025 10.21 그렇다면 해의 참 값은? 먼저, 모든 decimal 값을 유리수로 변환하고, solve 로 답을 구함. 변수 x로는 구해지는데 y로는 "Error: Resource exhaustion" 발생 // 이유는 모름. approx(exsol1) x=73.049507058547 and y=23.747548955927 2025 10.21