Operations

Cấu hình logrotate quản lý log trên VPS Ubuntu

Khi chạy một VPS trong thời gian dài, các file log của hệ thống và ứng dụng (Nginx, MySQL, Docker) âm thầm phình to, có thể chiếm hàng GB ổ đĩa. Nếu bạn không có kế hoạch dọn dẹp, một ngày đẹp trời bạn sẽ không SSH vào được vì ổ / đã đầy. Logrotate là công cụ có sẵn trên Ubuntu giúp bạn tự động hóa việc này: nén log cũ, xoay vòng theo thời gian, và xóa log quá hạn. Bài này hướng dẫn bạn cấu hình logrotate trên VPS Ubuntu 24.04 để quản lý log hiệu quả, giữ hệ thống luôn khỏe mạnh.

Yêu cầu trước khi bắt đầu

  • Một VPS chạy VPS Linux với Ubuntu 24.04 LTS (hướng dẫn tương thích Ubuntu 22.04, Debian 12).
  • Quyền truy cập root hoặc user sudo.
  • Các dịch vụ đã cài đặt (Nginx, MySQL, Docker…) đang chạy để thực hành.
  • Biết các lệnh cơ bản: nano, ls, cat.

Logrotate là gì và cơ chế hoạt động

Logrotate là daemon chạy định kỳ (mặc định mỗi ngày một lần qua cron) để xử lý các file log dựa trên cấu hình trong /etc/logrotate.conf và các file trong thư mục /etc/logrotate.d/. Cấu hình cơ bản gồm:

  • rotate: số file log cũ giữ lại (vd rotate 7).
  • daily/weekly/monthly: tần suất xoay.
  • compress: nén file bằng gzip.
  • delaycompress: trì hoãn nén 1 lần xoay (để ứng dụng kịp ghi tiếp).
  • missingok: không báo lỗi nếu file log chưa có.
  • notifempty: không xoay nếu file log rỗng.
  • postrotate: script chạy sau khi xoay log (vd reload Nginx).

Khi xoay, /var/log/nginx/access.log thành access.log.1, sau đó nén thành access.log.1.gz, rồi lần sau thành access.log.2.gz…, đến số rotate thì file cũ nhất bị xóa.

Kiểm tra logrotate đã được cài đặt chưa

Trên Ubuntu, logrotate được cài mặc định. Hãy kiểm tra:

sudo logrotate --version

Nếu chưa có, cài đặt:

sudo apt update && sudo apt install logrotate -y

VERIFY: chạy lệnh và xem trạng thái cronjob:

sudo systemctl status logrotate.timer

Kết quả hiển thị active (waiting) nghĩa là timer đang chờ lịch chạy.

Bước 1 - Tìm hiểu cấu hình logrotate mặc định của hệ thống

File cấu hình chính: /etc/logrotate.conf. Xem nội dung:

sudo cat /etc/logrotate.conf

Một số dòng quan trọng:

rotate 4
weekly
create
compress
include /etc/logrotate.d
/var/log/wtmp {
    missingok
    monthly
    create 0664 root utmp
    rotate 1
}

Giải thích: mặc định xoay hàng tuần, giữ 4 file cũ, nén, bao gồm các cấu hình riêng trong /etc/logrotate.d/. Hãy xem thư mục đó chứa gì:

ls -l /etc/logrotate.d/

Bạn sẽ thấy các file như apt, dpkg, rsyslog, ufw… Mỗi file là cấu hình riêng cho một dịch vụ.

Bước 2 - Cấu hình logrotate cho Nginx

Giả sử Nginx được cài mặc định, log nằm ở /var/log/nginx/access.logerror.log. Tạo file cấu hình riêng:

sudo nano /etc/logrotate.d/nginx

Dán nội dung sau:

/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        if [ -f /var/run/nginx.pid ]; then
            kill -USR1 `cat /var/run/nginx.pid`
        fi
    endscript
}

Giải thích:

  • daily: xoay mỗi ngày.
  • rotate 14: giữ log 14 ngày gần nhất.
  • sharedscripts: chỉ chạy script postrotate một lần cho tất cả file trong block.
  • kill -USR1: gửi tín hiệu yêu cầu Nginx mở lại file log mới (không reload cả service).

VERIFY cấu hình có đúng cú pháp không:

sudo logrotate -d /etc/logrotate.d/nginx

Nếu không có lỗi error, cấu hình hợp lệ. Chạy thử (force) để xem hoạt động:

sudo logrotate -f /etc/logrotate.d/nginx

Lúc này /var/log/nginx/access.log sẽ được xoay thành access.log.1. Kiểm tra:

ls -la /var/log/nginx/

Bước 3 - Cấu hình logrotate cho MySQL (MariaDB)

Log của MySQL thường ở /var/log/mysql/error.log/var/log/mysql/mysql-slow.log. Tạo file:

sudo nano /etc/logrotate.d/mysql
/var/log/mysql/*.log {
    daily
    missingok
    rotate 7
    compress
    delaycompress
    notifempty
    create 640 mysql adm
    sharedscripts
    postrotate
        if [ -x /usr/bin/mysqladmin ] && [ -f /var/run/mysqld/mysqld.pid ]; then
            /usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf flush-logs 2>/dev/null
        fi
    endscript
}

Lưu ý: lệnh flush-logs yêu cầu MySQL đóng log cũ và mở file mới. Đường dẫn đến mysqld.pid có thể khác tùy bản (Ubuntu 24.04 dùng MariaDB, pid ở /run/mysqld/).

VERIFY:

sudo logrotate -d /etc/logrotate.d/mysql
sudo logrotate -f /etc/logrotate.d/mysql  # chạy thử

Bước 4 - Cấu hình logrotate cho Docker container log

Log của Docker container (json-file driver) nằm ở /var/lib/docker/containers/*/*.log. Cỡ file có thể lên tới vài GB nếu không quản lý. Tạo file cấu hình:

sudo nano /etc/logrotate.d/docker-containers
/var/lib/docker/containers/*/*.log {
    rotate 7
    daily
    compress
    missingok
    delaycompress
    copytruncate
}

Giải thích: copytruncate là chìa khóa, nó copy file log sang file mới, rồi truncate (xóa nội dung) file gốc mà không cần kill/reload container. Docker không support USR1 dễ dàng, nên copytruncate là giải pháp an toàn.

VERIFY:

sudo logrotate -d /etc/logrotate.d/docker-containers

Bước 5 - Kiểm tra và debug logrotate tổng thể

Sau khi cấu hình xong, logrotate chạy tự động qua timer. Bạn có thể chạy thủ công để kiểm tra toàn bộ:

sudo logrotate -v -f /etc/logrotate.conf

Tham số -v in chi tiết từng bước. Xem log của logrotate:

sudo cat /var/log/logrotate.log

Nếu thấy lỗi (vd permission denied), kiểm tra quyền user sở hữu file log và tham số create.

Mẹo debug: nếu log không xoay, hãy kiểm tra trạng thái của file, logrotate chỉ xoay nếu file có nội dung và đã cũ hơn 1 chu kỳ (daily thì cũ hơn 1 ngày). Thử xóa dòng notifempty để buộc xoay ngay cả file rỗng.

Xử lý lỗi thường gặp

Lỗi "error: skipping because parent directory has insecure permissions"

Logrotate không xoay vì thư mục /var/log/nginx/ có permission quá lỏng lẻo (vd 777). Khắc phục: set lại owner và permission:

sudo chown root:adm /var/log/nginx
sudo chmod 750 /var/log/nginx

Lỗi web server không ghi log sau khi xoay

Khi dùng copytruncate (như Docker), file gốc bị truncate nhưng ứng dụng vẫn giữ file descriptor cũ, nên vẫn ghi tiếp. Nếu dùng create + kill signal mà web server vẫn ghi vào file cũ, hãy kiểm tra script postrotate có chạy đúng không:

sudo journalctl -u logrotate.service --since "5 minutes ago"

Logrotate không chạy đúng lịch

Kiểm tra timer systemd có active không:

sudo systemctl list-timers --all | grep logrotate

Nếu timer disabled, enable nó:

sudo systemctl enable --now logrotate.timer

Câu hỏi thường gặp

Có thể xoay log mỗi giờ không?

Có. Thay daily bằng hourly, nhưng cần cấu hình cron chạy mỗi giờ: copy file /lib/systemd/system/logrotate.timer thành /etc/systemd/system/ và sửa OnCalendar=hourly. Tuy nhiên, xoay quá thường xuyên có thể gây mất mát dữ liệu log nếu ứng dụng không kịp xử lý tín hiệu.

Sự khác giữa compress và delaycompress là gì?

compress nén file log ngay sau khi xoay. delaycompress trì hoãn nén đến lần xoay tiếp theo, ứng dụng vẫn cần ghi tiếp vào file cũ giây lát sau khi xoay, delaycompress giúp tránh lỗi "file đang được ghi". Nên dùng delaycompress cho dịch vụ ghi log liên tục.

Làm sao để xóa log cũ ngay lập tức?

Chạy lệnh logrotate với tham số -f (force) và --force-rotate:

sudo logrotate -f /etc/logrotate.d/nginx

Lưu ý: tham số rotate trong cấu hình quyết định số file giữ lại, nên sau khi xoay, file cũ sẽ bị xóa nếu vượt quá số rotate.

Logrotate có ảnh hưởng đến hiệu năng VPS không?

Rất ít. Quá trình chạy nhanh (vài giây) và chỉ chạy mỗi ngày một lần. Với nhiều dịch vụ lớn (cả trăm GB log), nén có thể gây CPU spike nhẹ, nhưng không đáng kể với VPS có 2-4 vCPU. Các gói thuê VPS NVMe phổ biến đều xử lý vượt trội.

Bài viết liên quan

Lưu ý: Bài viết mang tính tham khảo, tổng hợp kiến thức chung. Mỗi hệ thống, hạ tầng và nhu cầu có đặc thù riêng, nên kiểm thử trong môi trường an toàn và tham vấn kỹ sư trước khi triển khai thực tế.