首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Nginx 日誌切割、分析與自動化維護 Shell 腳本實戰

     編輯:Java 相關知識

背景說明

原標題為「Java 查詢 MongoDB ObjectId」,但實際內容為 Nginx 日誌自動化運維腳本集。本文整理三支核心腳本:日誌切割壓縮、定時清理、錯誤碼/URL/IP 分析,已在生產環境穩定運行。

1. 定時任務設定 (crontab)

# 每天 15:01 執行切割腳本,日誌輸出至 cron.log
1 15 * * * /home/dongnan/sh/split.sh >> /home/dongnan/sh/cron.log 2>&1

2. 日誌切割與壓縮腳本 (split.sh)

#!/bin/bash
# 變數區
log_dir=/var/log/nginx/
log_date=$(date +"%Y%m%d")
nginx_pid=/var/run/nginx.pid
keep_days=30

# 清理 30 天前的 .gz 壓縮檔
find "$log_dir" -name "*.log.gz" -type f -mtime +${keep_days} -exec rm -rf {} \;

# 重新命名當前 access.log / error.log 為 日期-檔名.log 並壓縮
for log_name in $(ls "$log_dir" | awk '/\.log$/'); do
    if [ -e "${log_dir}${log_date}-${log_name}" ]; then
        echo "${log_dir}${log_date}-${log_name} 已存在,跳過"
        continue
    fi
    mv "${log_dir}${log_name}" "${log_dir}${log_date}-${log_name}"
    gzip "${log_dir}${log_date}-${log_name}"
done

# 平滑重開 Nginx 讓它寫入新日誌檔
kill -USR1 $(cat $nginx_pid) && sleep 1

3. 進階切割腳本 (cutlog.sh) — 支援自訂路徑、保留 10 天、權限修正

#!/bin/bash
NGINX_BIN=$(ps aux | grep nginx | grep root | grep -v grep | awk '{print $14}')
if [ "$NGINX_BIN" = "/usr/local/nginx/sbin/nginx" ]; then
    ACCLOG=$(grep 'access_log' /usr/local/nginx/conf/nginx.conf | awk '{print $2}')
    ERRLOG=$(grep '^error_log' /usr/local/nginx/conf/nginx.conf | awk '{print $2}' | cut -d';' -f1)

    if [ -f "$ACCLOG" ]; then
        mv "$ACCLOG" "$ACCLOG.$(date -d '-1 day' +%F)"
        mv "$ERRLOG" "$ERRLOG.$(date -d '-1 day' +%F)"
        touch "$ACCLOG" "$ERRLOG"
        chown nginx:root "$ACCLOG" "$ERRLOG"
        [ -f /usr/local/nginx/logs/nginx.pid ] && kill -USR1 $(cat /usr/local/nginx/logs/nginx.pid)
        /mnt/logs/checklog.sh "$ACCLOG.$(date -d '-1 day' +%F)"  # 呼叫分析腳本
        gzip "$ACCLOG.$(date -d '-1 day' +%F)"
        gzip "$ERRLOG.$(date -d '-1 day' +%F)"
        # 移動 10 天前舊日誌至歸檔目錄
        mv "$ACCLOG.$(date -d '-10 day' +%F).*" /mnt/history.nginx.log/
        mv "$ERRLOG.$(date -d '-10 day' +%F).*" /mnt/history.nginx.log/
    fi
fi

4. 日誌分析腳本 (checklog.sh) — 40x/50x 錯誤、Top URL、Top IP

#!/bin/bash
LOG_FILE=$1
echo "####################$(date +%F)" >> /mnt/logs/400.txt
echo "####################$(date +%F)" >> /mnt/logs/URL.txt
echo "####################$(date +%F)" >> /mnt/logs/IP.txt

# 總行數 → IP.txt
wc -l < "$LOG_FILE" >> /mnt/logs/IP.txt

# 狀態碼統計 → CODE.txt
awk -F'"' '{print $3}' "$LOG_FILE" | awk '{print $1}' | sort | uniq -c | sort -rn > /mnt/logs/CODE.txt

# Top 20 IP → IP.txt
awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -rn | head -20 >> /mnt/logs/IP.txt

# 400+ 錯誤詳情 → 400.txt
while read count code; do
    if [ "$code" -ge 400 ]; then
        echo "#####FIND $code###############" >> /mnt/logs/400.txt
        grep "\" $code " "$LOG_FILE" | grep -v ' "-" "-" - ' | \
        awk '{print $1,$2,$3,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21}' | \
        sort | uniq -c | sort -rn | head -5 >> /mnt/logs/400.txt
    fi
done < /mnt/logs/CODE.txt

# Top 20 URL(去除查詢字串、正規化 review 下載路徑) → URL.txt
grep -v ' "-" "-" - ' "$LOG_FILE" | \
awk -F'T' '{print $2}' | awk -F'?' '{print $1}' | \
sed 's|\(/review/file/download/\).*|\1|' | \
sort | uniq -c | sort -rn | head -20 >> /mnt/logs/URL.txt

關鍵指令速查

指令用途
kill -USR1 `cat nginx.pid`平滑重開,讓 Nginx 切換到新日誌檔
awk -F'"' '{print $3}'以雙引號分欄,取第 3 欄(含狀態碼)
uniq -c | sort -rn計數並倒序排序
date -d '-1 day' +%F取前一天日期 (YYYY-MM-DD)

部署清單

  1. 將三支腳本放入 /home/dongnan/sh/ 並 chmod +x。
  2. 建立歸檔目錄 /mnt/history.nginx.log/、分析輸出目錄 /mnt/logs/。
  3. 驗證 nginx.pid 路徑與 nginx.conf 中 log 路徑一致。
  4. 加入 crontab 定時執行。

三支腳本覆蓋「切割→壓縮→分析→歸檔」全生命週期,零依賴、純 Shell 實現,適合任何 Linux+Nginx 環境直接落地。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved