Log rotation trên Linux

Vấn đề ghi log và debug

Hồi mới tập tọe làm các dự án ở công ty, hầu hết ai cũng chỉ chăm chăm vào làm chức năng cho được, ít để ý đến những thứ râu ria bên ngoài (hay chỉ có mỗi mình như thế?). Việc ghi log cũng vậy. Trên môi trường local, việc debug rất tiện lợi và nhanh chóng khi có nhiều công cụ hỗ trợ, thậm chí việc xem log và debug còn interactive trên STDOUT rất trực quan (như Rails chẳng hạn). Khi đưa lên production, căn cứ để mà debug gần như là phải xem log, log của hệ thống, log của bản thân ứng dụng... Nhưng lỗi trên môi trường production thường xảy ra với tần suất thấp, cộng với việc theo như mặc định, chỉ có 1 file log duy nhất cho cả ứng dụng, khi đó, lần mò vào log, khoanh vùng khoảng thời gian xảy ra lỗi, sẽ như mò kim đáy bể.

$ ls -l log
-rw-r--r-- 1 root root 2.2G Dec  3 09:25 production.log
-rw-r--r-- 1 root root 998M Oct 23 14:50 sidekiq.log
-rw-r--r-- 1 root root 150M Oct 23 14:52 whenever.log

Chưa hết, môi trường production phục vụ cho rất nhiều người dùng, lượng log cũng tăng dần lên gây chiếm bộ nhớ lưu trữ máy chủ, để đó cũng không xong mà xóa tiệt nội dung cũ đi cũng không ổn, nhỡ có đoạn log về một lỗi hiếm gặp nằm trong đó thì sao?
Log rotation! I choose you!

Log rotation là gì?

  • Là một công cụ hỗ trợ quản lý file log trên hệ thống.
  • Nôm na là thế này, ví dụ hệ thống của bạn hoạt động được 10 ngày, theo cách ghi log cũ là chỉ có 1 file duy nhất cho 10 ngày đó. Khi có logrotate can thiệp, mỗi ngày nó sẽ đưa nội dung log của ngày hôm trước ra một file riêng đặt tên theo ngày tháng tương ứng, nó còn có thể nén các file cũ đó lại để tiết kiệm dung lượng. Chưa hết, ta có thể quy định cho nó giữ lại tối đa bao nhiêu file tùy ý, 10 file chẳng hạn, thì đến ngày thứ 11, file của ngày đầu tiên sẽ bị xóa, đây cũng chính là ý nghĩa của từ rotation - xoay vòng.
$ ls -l log
-rw-r--r-- 1 ruby apache 201M Dec  3 03:00 production.log
-rw-r--r-- 1 ruby apache 200M Dec  2 03:00 production.log-20191202
-rw-r--r-- 1 ruby apache 198M Dec  1 03:00 production.log-20191201
-rw-r--r-- 1 ruby apache 210M Nov 30 03:45 production.log-20191130
-rw-r--r-- 1 ruby apache 199M Nov 29 03:00 production.log-20191129
-rw-r--r-- 1 ruby apache 199M Nov 28 03:00 production.log-20191128
-rw-r--r-- 1 ruby apache 150M Nov 27 03:00 production.log-20191127
-rw-r--r-- 1 ruby apache 221M Nov 26 03:01 production.log-20191126
-rw-r--r-- 1 ruby apache 200M Nov 25 03:00 production.log-20191125
-rw-r--r-- 1 ruby apache 201M Nov 24 03:00 production.log-20191124
-rw-r--r-- 1 ruby apache 200M Nov 23 03:00 production.log-20191123
  • Logrotate đơn thuần là một chương trình hoạt động theo việc xếp lịch vào crontab chứ không có gì ghê ghớm cả.
  • Khi đó, không gian lưu trữ của hệ thống sẽ được kiểm soát, không bị phình to, và vì chia ra các mốc nhỏ, nên việc tìm kiếm lại thông tin sẽ dễ dàng hơn.
  • Để làm được rotation như trên thì hãy xem cách cấu hình bên dưới.

Cấu hình logrotate cơ bản

Mặc định Logrotate được cài đặt trên hầu hết các bản phân phối Linux. Nếu chưa thì cài đặt cũng rất đơn giản. Google nhé!

Logrotate có một file cấu hình mặc định tại /etc/logrotate.conf, trong đây chứa một số cấu hình có thể tham khảo làm mẫu. Còn thường khi muốn cấu hình logrotate cho ứng dụng cụ thể, ta sẽ tạo từng file riêng biệt trong folder /etc/logrotate.d/. Ví dụ:

:: /etc/logrotate.d/my-app.conf

/var/log/my-app/log/*.log {
    daily
    dateext
    dateformat %Y-%m-%d.
    notifempty
    missingok
    rotate 10
    compress
    delaycompress
    create 640 ruby apache
}
  • /var/log/my-app/log/*.log: chỉ định file log sẽ được rotate. Ở đây có thể chỉ định nhiều file bằng dấu *, hoặc một file cụ thể nào đấy bằng tên chính xác.
  • daily: chu kỳ xoay vòng, ngoài daily còn có weekly, monthly, yearly.
  • dateext: thêm hậu tố thời gian vào cuối tên các file log cũ, mặc định là YYYYMMDD, ví dụ: production.log-20191123. Nếu không có tùy chọn này, mặc định các file cũ sẽ có hậu tố là số tăng dần 1, 2, 3,...
  • dateformat: tùy chỉnh định dạng ngày tháng. Ngoài ra nếu thêm dấu chấm (.) vào cuối, phần hậu tố thời gian sẽ được thêm vào phía trước file extension, không làm thay đổi extension của file. Ví dụ: production-20191123.log. (phụ thuộc vào dateext)
  • notifempty: không rotate nếu file gốc bị rỗng.
  • missingok: không báo lỗi nếu chẳng may file gốc bị mất. Ngược lại chúng ta có nomissingok, khi đó sẽ xuất ra thông báo lỗi, đây là option mặc định.
  • rotate [count]: số lượng file log cũ được giữ lại.
  • compress: nén file log cũ. Mặc định sẽ nén bằng gzip, còn muốn thay đổi chương trình nén thì có option compresscmd [prog] với các tùy chọn gzip, zip, xz hoặc bzip2.
  • delaycompress: file cũ sẽ không được nén luôn khi tạo ra, mà sẽ chờ đến chu kỳ sinh ra file mới tiếp theo. (phụ thuộc vào compress)
  • create [mode] [owner] [group]: kiểm soát phân quyền cho file log được rotate (đối với một số hệ thống có yêu cầu cụ thể về quyền). Như ví dụ trên file rotate sẽ được tạo ra với mode 640, thuộc user ruby và group apache.
  • Ngoài xoay vòng theo chu kỳ thời gian, ta có thể xoay vòng theo dung lượng, với option size [value], value sẽ gồm giá trị và đơn vị dung lượng, gồm có k: kilobytes, M: megabytes, G: gigabytes. Ví dụ: 100k, 100M, 100G. Khi size được khai báo cùng với chu kỳ ngày tháng, nó sẽ ưu tiên rotate theo size mà bỏ qua ngày tháng.

Trên đây là những options cơ bản, ngoài ra các bạn có thể tham khảo tài liệu của logrotate để có nhiều options hơn: https://linuxconfig.org/logrotate-8-manual-page

Khi đã có file cấu hình, muốn kiểm tra xem format đã chuẩn chưa, ta dùng lệnh:

$ logrotate -d /etc/logrotate.d/my-app.conf

Muốn thực hiện rotate ngay mà không cần chờ chu kỳ hoặc size:

$ logrotate -vf /etc/logrotate.d/my-app.conf

Trong đó:

  • v: xuất thêm thông tin debug phòng khi bạn muốn dò lỗi.
  • f: rotate ngay lập tức.

Tổng kết

Logrotate là một cách quản lý log rất hay, giúp chia nhỏ log nhằm dễ tìm kiếm thông tin, việc chỉ giữ lại một lượng log nhất định cũng giúp dung lượng lưu trữ không bị phình to. Nhiều khách hàng sẽ than phiền khi server của họ hết dung lượng quá nhanh do log quá nhiều, khi đó ngoài việc dùng logrotate, chúng ta cũng nên kiểm soát những gì được ghi ra log, tránh ghi quá nhiều thông tin không cần thiết, sau này dò lại cũng đỡ hoa mắt.

Happy rotating!