熱門分類
載入中…
目錄0%

🐧 Linux LogRotate 日誌自動輪替與清理教學(含 systemd / cron 實作)

    🐧 Linux LogRotate 日誌自動輪替與清理教學(含 systemd / cron 實作)

    維運環境中,日誌若不規劃,磁碟容易被塞滿、分析也變困難。LogRotate 可針對大小或時間自動分檔、壓縮與清理,並在輪替後重載服務。本文提供 一步一步 的實作範例,並解釋 systemd timercron.daily 兩種啟動方式,最後附上常見錯誤排查清單與安全最佳實務。

    📑 目錄

    一、核心概念與檔案佈局

    • 主設定檔:/etc/logrotate.conf(放全域規則與 include 指令)。
    • 服務分檔:/etc/logrotate.d/*(各服務各寫一份)。
    • 運作模式:時間(daily/weekly/monthly)大小(size) 輪替;可選擇 compress/delaycompressrotate Nmissingoknotifempty 等。
    • 輪替後動作:postrotate/endscript 內呼叫 systemctl reloadkill -HUP 讓服務重載。

    二、全域設定:/etc/logrotate.conf

    # /etc/logrotate.conf
    # 全域預設(可被 /etc/logrotate.d/* 覆寫)
    weekly                 # 每週輪替
    rotate 4               # 保留 4 份歷史檔
    create                 # 建立新檔,沿用預設權限(可於個別檔案強化)
    dateext                # 使用日期作為副檔名
    compress               # 壓縮舊檔(搭配 delaycompress 更安全)
    include /etc/logrotate.d
    
    # 針對 wtmp/btmp 的示例(系統登入紀錄)
    /var/log/wtmp {
      monthly
      rotate 12
      create 0664 root utmp
      missingok
    }
    /var/log/btmp {
      monthly
      rotate 12
      create 0600 root utmp
      missingok
    }

    三、每服務配置:/etc/logrotate.d/ 範例

    範例 A:Nginx 存取/錯誤日誌
    # /etc/logrotate.d/nginx
    /var/log/nginx/*.log {
      weekly
      rotate 8
      size 50M
      missingok
      notifempty
      compress
      delaycompress
      dateext
      create 0640 www-data adm
      sharedscripts
      postrotate
        # 以重載方式讓 Nginx 重新打開檔案句柄
        [ -s /run/nginx.pid ] && systemctl reload nginx.service
      endscript
    }
    範例 B:應用程式單一檔案(支援 copytruncate)
    # /var/log/myapp/app.log 若程式無法 HUP 重載,可用 copytruncate
    /var/log/myapp/app.log {
      daily
      rotate 14
      size 10M
      missingok
      notifempty
      compress
      delaycompress
      dateext
      copytruncate       # 先複製舊檔再 truncate 原檔,避免重啟服務
    }
    範例 C:多檔規則 + 權限強化
    # /etc/logrotate.d/myapps
    /var/log/myapps/*.log {
      weekly
      rotate 6
      missingok
      notifempty
      compress
      dateext
      su root adm         # 以 logrotate 的 su 機制維持權限
      create 0640 root adm
    }

    四、排程觸發:systemd timer vs cron.daily

    大多數新版發行版已使用 logrotate.timer;舊版則由 /etc/cron.daily/logrotate 觸發。

    # ✅ 建議:啟用 systemd timer(具可觀察性、易管理)
    sudo systemctl enable --now logrotate.timer
    systemctl status logrotate.timer
    systemctl list-timers | grep logrotate
    
    # 若使用傳統 cron(依發行版預設)
    ls -l /etc/cron.daily/logrotate
    sudo run-parts /etc/cron.daily   # 立即觸發每日工作(測試用)

    何者優先? 若同時存在,請擇一;避免「timer + cron」雙重觸發導致並行輪替。

    五、驗證與手動輪替

    # 乾跑(不實作),檢查設定是否正確
    sudo logrotate -d /etc/logrotate.conf
    
    # 強制輪替(測試實作)
    sudo logrotate -f /etc/logrotate.conf
    
    # 觀察結果與壓縮檔
    ls -lh /var/log/nginx/
    ls -lh /var/log/myapp/

    六、常見錯誤與排查

    • Permission denied/無法建立新檔:為規則加入 create 0640 user group 或使用 su 子句。
    • 輪替後服務仍寫入舊檔:多半是服務未重載;在 postrotate 呼叫 systemctl reload 或使用 copytruncate
    • 並行輪替衝突:避免 logrotate.timercron.daily 同時啟用;關閉其一。
    • 壓縮檔未出現:檢查是否設了 delaycompress(壓縮會延後到下一次輪替)。
    • 容量未下降:輪替後未重載的服務仍持有檔案描述符;lsof | grep deleted 可查已刪但被佔用的檔案。

    七、安全與最佳實務(Hardening)

    • 最小化權限:重要日誌使用 create 0600 root adm,避免一般使用者可讀。
    • 避免覆寫:優先使用 createcopytruncate,不要用手動 > file 方式清空。
    • 保留週期依合規:依內控/法規需求設定 rotate N(例如安全稽核要求保留 6–12 個月)。
    • 與集中化搭配:關鍵日誌建議輸出到集中式(rsyslog/Logstash),輪替僅做本機控重。

    八、實用 Recipes(可直接套用)

    R1:高流量網站的「時間 + 大小」雙條件
    /var/log/nginx/*.log {
      daily
      size 100M
      rotate 14
      missingok
      compress
      delaycompress
      dateext
      create 0640 www-data adm
      sharedscripts
      postrotate
        systemctl reload nginx.service
      endscript
    }
    R2:journald 清理(配合 LogRotate 的容量治理)
    # 設定 journald 儲存上限(/etc/systemd/journald.conf)
    SystemMaxUse=2G
    SystemMaxFileSize=200M
    RuntimeMaxUse=512M
    
    # 立即清理舊日誌(保留 14 天內)
    sudo journalctl --vacuum-time=14d
    # 或依容量清理,保留最近 1G
    sudo journalctl --vacuum-size=1G
    R3:自訂任務以 timer 週期掃除大型暫存檔
    # /etc/systemd/system/tmp-clean.service
    [Unit]
    Description=Scheduled temp cleanup
    
    [Service]
    Type=oneshot
    ExecStart=/usr/bin/find /var/tmp -type f -mtime +7 -delete
    
    # /etc/systemd/system/tmp-clean.timer
    [Unit]
    Description=Run temp cleanup daily
    
    [Timer]
    OnCalendar=daily
    RandomizedDelaySec=120
    Persistent=true
    
    [Install]
    WantedBy=timers.target
    
    # 啟用
    sudo systemctl enable --now tmp-clean.timer
    systemctl list-timers | grep tmp-clean

    🧭 行動清單

    ✅ 啟用 logrotate.timer(或確認 cron.daily)並擇一
    ✅ 為 Nginx / 應用服務增設 /etc/logrotate.d/ 個別規則
    ✅ 以 logrotate -d 與 -f 驗證流程;搭配 journalctl 觀察
    ✅ 對安全性高的日誌採 create 0600 與 su 權限控管
    ✅ 搭配 rsyslog / GoAccess 做集中化與可視化

    — WWFandy・主題筆記

    🔗 分享這篇 LINE Facebook X

    沒有留言:

    字級