Rotate Rails logs with Logrotate

Trong khi phát triển hay khi đã đưa lên môi trường production thì log của một ứng dụng luôn luôn rất quan trọng cho công việc phân tích và debug mỗi khi có phát sinh sự cố. Nhưng sẽ ra sao nếu file log của chúng ta nó phình lên quá lớn? Nó sẽ rất khó để phân tích (hoặc debug) và sẽ rất tốn tài nguyên mỗi khi ứng dụng thực hiện ghi log vào file rất lớn đó. Vậy, việc đầu tiên chúng ta nghĩ tới là cần phải chia nhỏ file log này ra theo ngày để dễ quản lý và tăng hiệu suất khi log được thêm bởi ứng dụng. Tiêu đề bài viết thì là dành cho ứng dụng Rails nhưng nội dung bài viết này mình sẽ chú tâm vào việc giới thiệu về ứng dụng Logrotate trên họ *nix nhé 😄!

Logrotate

Logrotate được thiết kế để dễ dàng quản lý các hệ thống tạo ra một lượng lớn các tập tin log. Nó tự động xoay (thay file mới), nén, xóa và gửi các file log lên các hệ thống lưu trữ hoặc email. Mỗi file log sẽ được xử lý hằng ngày (daily), hằng tuần (weekly), hằng tháng (monthly) hoặc khi nó phình đến một kích thước nhất định nào đó.

Thông thường Logrotate được chạy hằng ngày (daily cron job). Nó sẽ không sửa đổi file log mà chỉ thực hiện việc đổi tên file log hiện tại và tạo một file log mới thay vào vị trí của file cũ. Chúng ta cùng đi tìm hiểu thằng Logrotate này nhé. Đầu tiên sẽ là các tùy chọn của nó.

Các tùy chọn

  • -d, --debug
    • Bất chế độ debug, giống với tham số -v. Khi sử dụng tùy chọn này sẽ không có sự thay đổi cho các file log (giống kiểu chạy để kiểm thử xem nó sẽ thực hiện như thế nào ấy 😄)!
  • -f, --force
    • Ép Logrotate chạy kể cả khi nó cảm thấy rằng các file log không cần phải thực hiện rotate. Được sử dụng khi bạn thêm mới một mục vào cài đặt cho Logrotate hoặc khi file log cũ đã bị xóa bằng tay và Logrotate sẽ tạo ra file log mới để cho việc thực hiện ghi log sẽ được tiếp tục một cách chính xác
  • -m, --mail <command>
    • Thông báo với Logrotate rằng chúng ta muốn nó gửi các bản log đã được rotate tới email của chúng ta, mặc định nó sẽ sử dụng lệnh /bin/mail -s để gửi mail. Tùy chọn này nhận hai tham số là:
      1. Tiêu đề của email
      2. Người nhận
  • -s, --state <statefile>
    • Thông báo với Logrotate rằng bạn muốn sử dụng một state file khác (file chứa thông tin trạng thái của các cài đặt cho Logrotate). Mặc định file state được chứa ở /var/lib/logrotate/status.
  • --usage
    • Hiện thị thông tin tóm tắt về cách sử dụng Logrotate
  • -?, --help
    • Hiển thị thông tin trợ giúp
  • -v, --verbose
    • Bật chế độ hiển thị chị tiết khi thực hiện chạy Logrotate

Logrotate configurations

Logrotate sẽ xử lý tất các các log file bằng cách đọc các cấu hình từ file cài đặt tương ứng với mỗi ứng dụng mà chúng ta muốn Logrotate xử lý. Mỗi file cấu hình có thể tạo các tùy chọn global (các tùy chọn local sẽ đè lên các tùy chọn global và các tùy chọn khai báo sau sẽ đè lên các tùy chọn được khai báo ở trước đó) và xác định các file log sẽ được rotate. Các tùy chọn trong file cấu hình của Logrotate được gọi là các directive. Dưới đây sẽ là các directive mà bạn có thể sử dụng trong file cấu hình cho Logrotate sẽ thực hiện với log của ứng dụng:

  • compress
    • Các phiên bản cũ của tập tin log sẽ được nén lại. Mặc định là sử dụng gzip.
  • compresscmd
    • Xác định câu lệnh sẽ được chạy khi sử dụng gzip
  • uncompresscmd
    • Xác định cậu lệnh để giải nén các file log đã được nén. Mặc định sử dụng lệnh gunzip
  • compressext
    • Xác định extension của tập tin nén (nếu compress được bật). Mặc định sẽ sử dụng các cài đặt của compresscmd
  • compressoptions
    • Lệnh sẽ được truyền cho chương trình nén. Mặc định cho gzip-9 (mức nén cao nhất)
  • copy
    • Tạo một bản sao của file log và không thay đổi file log gốc. Tùy chọn có thể sử dụng khi bạn muốn tạo ra các bản ảnh chụp cho file log hiện tại. Khi tùy chọn này được sử dụng thì tùy chọn create sẽ không có tác dụng.
  • copytruncate
    • Cắt file log gốc sau khi đã tạo ra một bản sau của file log thay vì di chuyển file log cũ và tạo ra một file log mới. Lưu ý rằng khi sử dụng tùy chọn này bạn sẽ chấp nhận có thể mất một số đoạn log do việc chênh lệch thời gian giữa cắt và tạo. Khi tùy chọn này được sử dụng thì tùy chọn create sẽ không có tác dụng.
  • create mode owner group
    • Cài đặt cho file log đã được rotate sẽ được tạo như thế nào. Bạn có thể vô hiệu hóa tùy chọn này bằng cách sử dụng tùy chọn nocreate.
      • mode: Mode của file (giống lệnh chmod).
      • owner: Xác định user nào sẽ là chủ của file log được tạo
      • group: Nhóm người dùng mà file log được tạo ra sẽ thuộc về.
  • daily
    • Thực hiện rotate log hằng ngày
  • dateext
    • Sử dụng định dạng YYYYMMDD cho tên file log cũ thay vì thêm số vào tên file log. Tùy chọn này có thể được thay đổi khi bạn sử dụng tùy chọn dateformat
  • dateformat format_string
    • Cài đặt định dạng ngày tháng cho tùy chọn dateext. Nó gần giống với phương thức strftime. Chỉ có tùy chọn %Y, %m, %d%s được phép sử dụng. Giá trị mặc định là %Y%m%d.
  • delaycompress
    • Hoãn việc nén file log cũ sang chu kỳ thực hiện rotate tiếp theo. Ví dụ chúng ta thực hiện rotate log hằng ngày. Ngày 21, 22 và 23 thì chỉ có file log của ngày 21 được nén. Còn ngày 22 phải chờ sang chu kỳ của ngày 24 mới được nén. Tùy chọn này chỉ có tác dụng khi bạn sử dụng tùy chọn compress.
  • extension ext
    • Phần mở rộng của file log sau khi được rotate. Nếu tùy chọn compress được sử dụng, thì extension của nó sẽ là ext.gz.
  • ifempty
    • Thực hiện rotate file log trong cả trường hợp file log đó rỗng. Tùy chọn này sẽ đè tùy chọn notifempty (ifempty mặc định được bật).
  • mail address
    • Thực hiện gửi mail tới address khi số lượng file log cũ đã vượt qua giới hạn giữ lại của cài đặt rotate.
  • mailfirst
    • Khi sử dụng lệnh mail thì file log được rotate sẽ được gửi luôn thay vì phải đợi cho đến khi số lượng các bản log được rotate vượt quá quy định.
  • maillast
    • Ngược lại với mailfirst. Là sẽ gửi các file log được rotate khi số lượng file log vượt quá số lượng do chúng ta quy định.
  • maxage count
    • Xóa các file log được rotate nếu nó cũ hơn số ngày (count). count này chỉ được áp dụng cho các file log đã được rotate và các file này sẽ được gửi về mail nếu chúng ta sử dụng tùy chọn mailfirst hoặc maillast.
  • minsize size
    • Cài đặt log file sẽ được rotate nếu kích thước của nó lớn hơn size byte. Tùy chọn này sẽ thay thế các tùy chọn daily, weekly, monthlyyearly.
  • missingok
    • Sử dụng để thông báo với Logrotate rằng nếu một file log bị thiếu, thì hãy sang rotate file log tiếp theo thay vì báo lỗi.
  • monthly
    • Thực hiện rotate các file log hằng tháng (thường là ngày đầu tiên của tháng).
  • nocompress
    • Sẽ không nén các file log cũ
  • nocopy
    • Không thực hiện copy file log gốc (tùy chọn này sẽ ghi đè tùy chọn copy)
  • nocopytruncate
    • Không truncate file log gốc sau khi thực thực hiện copy (tùy chọn này sẽ ghi đè tùy chọn copytruncate)
  • nocreate
    • Không tạo ra các file log mới (tùy chọn này sẽ ghi đè tùy chọn create)
  • nodelaycompress
    • Không hoãn việc nén các file log đã được rotate sang chu kỳ rotate mới (tùy chọn này ghi đè tùy chọn delaycompress)
  • nodateext
    • Không lưu file log cũ với phần mở rộng là ngày tháng (tùy chọn này sẽ đè tùy chọn dateext)
  • nomail
    • Không gửi các file log cũ về mail
  • nomissingok
    • Nếu một file log không tồn tại. Thông báo lỗi rồi dừng lại (mặc định được sử dụng)
  • noolddir
    • Các file log được rotate sẽ đặt cùng thư mục với các file log (tùy chọn này sẽ đè tùy chọn olddir)
  • nosharedscripts
    • Thực hiện các câu lệnh trong khối prerotatepostrotate cho từng file log được rotate (tùy chọn này là mặc định và ghi đè tùy chọn sharedscripts). Đường dẫn tuyệt đối đến file log được truyền vào khối lệnh ở vị trí tham số đầu tiên. Nếu các câu lệnh trong khối có lỗi xảy ra (exit code khác 0) thì các hành động tiếp theo sẽ không được thực thi cho mình file log hiện tại.
  • noshred
    • Không sử dụng shred khi thực hiện xóa các file log đã cũ
  • notifempty
    • Không thực hiện rotate file log nếu file log rỗng (tùy chọn này sẽ đè tùy chọn ifempty).
  • olddir directory
    • Các file log được rotate sẽ được chuyển đến directory. Tùy chọn này có thể ghi đè tùy chọn noolddir
  • postrotate/endscript
    • Các lệnh trong khối này sẽ được thực thi (sử dụng /bin/sh) sau khi rotate một file log.
  • prerotate/endscript
    • Các lệnh trong khố này sẽ được thực thi (sử dụng /bin/sh) trước khi file log được rotate và chỉ thực thi khi file log đó thực sự được rotate.
  • firstaction/endscript
    • Các lệnh trong khối này sẽ được thực thi (sử dụng /bin/sh) một lần trước việc tất cả các file log được thực hiện rotate. Các lệnh này sẽ thực hiện trước các lệnh trong prerotate và chỉ thực hiện nếu có ít nhất một file log thực sự được rotate.
  • lastaction/endscript
    • Các lệnh trong khối này sẽ được thực thi (sử dụng /bin/sh) một lần sau khi tất cả các file log đã được rotate. Các lệnh này thực hiện sau các lệnh trong khối postrotate và chỉ thực hiện nếu có ít nhất một file log thực sự được rotate.
  • rotate count
    • Số lượng các file log count được rotate sẽ giữ lại trước khi nó được xóa hoặc được gửi về mail (nếu sử dụng directive mail). Nếu count là 0 thì file log được rotate sẽ bị xóa ngay sau khi thực hiện rotate.
  • size size
    • Log file sẽ được rotate nếu nó lớn hơn kích thước size byte (ví dụ: size 100, size 100k, size 100M, size 100G).
      • k cho Kylobytes
      • M cho Megabytes
      • G cho Gigabytes
  • sharedscripts
    • Bình thường, các lệnh trong khối prerotatepostrotate sẽ được thực thi cho từng file log riêng biệt. Nếu bạn sử dụng directive này thì các lệnh trong hai khối trên sẽ chạy chung (và một lần) cho tất cả các file log.
  • shred
    • Xóa các file log bằng lệnh shred -u thay vì sử dụng unlink().
  • shredcycles count
    • Số vòng count của lệnh shred. Bạn có thể tham khảo tùy chọn --n, --interations=N của Shred tại đây!
  • start count
    • Là số bắt đầu để Logrotate đếm. Ví dụ, nếu bạn sử dụng số 0. Thì các file log được rotate sẽ bắt đầu từ 0 (ví dụ: development.log.0, development.log.1, ...). Còn bạn sử dụng số 9 thì sẽ .9 thay vì phải bắt đầu từ 0-8.
  • weekly
    • Thực hiện rotate các file log nếu lần thực hiện cuối cùng đã lớn hơn một tuần. Tùy chọn này cũng giống với việc thực hiện rotate file vào ngày đầu tiên của tuần. Nhưng nó làm việc tốt hơn với trường hợp logrotate không được chạy vào mỗi đêm.
  • yearly
    • Thực hiện rotate các file log nếu file log cuối cùng được thực hiện trước đó hơn một năm.

Vậy là đã xong phần giới thiệu về thằng Logrotate (mục đích chính của bài viết này). Bây giờ chúng ta sang phần cài đặt Logrotate cho ứng dụng Rails của chúng ta nhé (rõ ràng là tiêu đề bài viết nhưng lại bị coi là phần phụ :v)!

Đầu tiên, chúng ta hãy tạo một file mới với tên tùy chọn vào thư mục /etc/logrotate.d/ với lệnh: sudo nano /etc/logrotate.d/<logrotate_config_file> với nội dung dưới đây (bạn có thể sửa lại cho phù hợp với danh sách các directives mà mình đã giới thiệu ở trên):

/path/to/project/log/*.log {
  daily
  create <mode> <user> <group>
  rotate 30
  missingok
  compress
  delaycompress
  notifempty
}

Sau đó bạn thử bằng lệnh: sudo logrotate /etc/logrotate.d/<logrotate_config_file> rồi xem kết quả ở file state bằng lệnh: cat /var/lib/logrotate/status.

Để Logrotate được thực hiện hằng ngày, bạn kiểm tra xem có file logrotate trong thư mục /etc/cron.daily/ hay không. Nếu không có, bạn cần tạo một file với nội dung sau:

#!/bin/sh

# Clean non existent log file entries from status file
cd /var/lib/logrotate
test -e status || touch status
head -1 status > status.clean
sed 's/"//g' status | while read logfile date
do
    [ -e "$logfile" ] && echo "\"$logfile\" $date"
done >> status.clean
mv status.clean status

test -x /usr/sbin/logrotate || exit 0
/usr/sbin/logrotate /etc/logrotate.conf

Rồi cho phép nó thực thi với mode executable với lệnh: sudo chmod +x /etc/cron.daily/logrotate.

Nếu bạn có biết và sử dụng Fabric và muốn thực hiện việc cài đặt Logrotate cho ứng dụng của mình trên nhiều server cùng lúc thì bạn có thể tham khảo fabfile của mình ở đây nhé ^^!

Thế là xong. Bài viết của mình đến đây là kết thúc. Hy vọng bài viết này sẽ giúp ích được cho bạn 😄! Hẹn mọi người ở các bài viết tiếp theo. Chào thân ái và quyết thắng :byebye:!

Link tham khảo:


All Rights Reserved