Hướng dẫn

Nhật ký (log) trong Linux: journalctl, /var/log, rsyslog và logrotate

Cập nhật: · Skillaria.Top

Trên các bản phân phối Linux hiện đại, journald thu thập log và bạn đọc chúng bằng journalctl: journalctl -u nginx hiển thị log của một dịch vụ, -f theo dõi theo thời gian thực, còn --since và -p lọc theo thời gian và mức độ quan trọng. Log dạng văn bản nằm trong /var/log, do rsyslog hoặc chính ứng dụng ghi, còn logrotate định kỳ nén và xóa các file cũ để ổ đĩa không bị đầy.

Khi một dịch vụ bị dừng giữa đêm, câu trả lời gần như luôn nằm trong log, vấn đề chỉ là tìm chúng ở đâu. Trên các bản phân phối hiện đại (Ubuntu, Debian, RHEL, Fedora, Arch), dịch vụ journald thu thập sự kiện, còn đọc chúng bằng lệnh journalctl. Song song đó, nhiều chương trình ghi log dạng văn bản vào /var/log, và logrotate theo dõi kích thước của chúng. Dưới đây là cách làm việc thực tế với log trong Linux bằng journalctl, nơi lưu các nhật ký khác, và cách không làm mất thông tin quan trọng khi xoay vòng log.

Log trong Linux được lưu ở đâu

Có ba nguồn, nên hãy hình dung chúng như một bản đồ:

  • journald — nhật ký nhị phân của systemd. Nhận stdout và stderr của mọi dịch vụ, thông báo của kernel và syslog. Được lưu trong /var/log/journal/ (lâu dài) hoặc /run/log/journal/ (chỉ đến lần khởi động lại tiếp theo).
  • /var/log — các file văn bản. Được ghi bởi rsyslog (ví dụ /var/log/syslog, /var/log/auth.log) hoặc bởi chính ứng dụng: nginx, PostgreSQL, MySQL.
  • Bộ đệm vòng của kernel — thông báo của driver và phần cứng, xem bằng dmesg hoặc journalctl -k.
FileNội dung
/var/log/syslog (Debian/Ubuntu)nhật ký hệ thống chung
/var/log/messages (RHEL/Fedora)tương đương trong họ Red Hat
/var/log/auth.log hoặc /var/log/secuređăng nhập, sudo, SSH
/var/log/kern.logthông báo của kernel
/var/log/dpkg.log, /var/log/apt/cài đặt gói
/var/log/nginx/access.log và error.log của web server
/var/log/wtmp, /var/log/btmpnhật ký đăng nhập dạng nhị phân, đọc qua last và lastb

Phần lớn file trong /var/log chỉ root hoặc nhóm adm đọc được, nên các lệnh xem thường phải chạy với sudo.

journalctl: các lệnh cơ bản

Không có tham số, journalctl in toàn bộ nhật ký từ bản ghi cũ nhất qua trình xem less. Ít khi cần như vậy — thường thu hẹp kết quả ngay từ đầu.

journalctl              # toàn bộ nhật ký, từ cũ đến mới
journalctl -e           # mở ngay ở cuối
journalctl -n 50        # 50 dòng gần nhất
journalctl -r           # đảo ngược, mới nhất ở trên
journalctl --no-pager   # không dùng less, tiện cho script và grep

Trong trình xem hoạt động các phím quen thuộc của less: / — tìm kiếm, G — xuống cuối, q — thoát. Các dòng dài bị cắt theo chiều rộng màn hình; phím mũi tên trái và phải cuộn ngang.

Log của một dịch vụ cụ thể: journalctl -u

Tình huống hay gặp nhất là xem một unit systemd đã ghi gì. Không cần tìm file và grep:

$ sudo journalctl -u nginx -n 20
Oct 14 03:12:41 web1 systemd[1]: Starting nginx.service - A high performance web server...
Oct 14 03:12:41 web1 nginx[1834]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Oct 14 03:12:41 web1 systemd[1]: nginx.service: Control process exited, code=exited, status=1/FAILURE
Oct 14 03:12:41 web1 systemd[1]: nginx.service: Failed with result 'exit-code'.

Tùy chọn -u có thể lặp lại: journalctl -u nginx -u php8.2-fpm hiển thị log của cả hai dịch vụ xen kẽ theo thời gian, hữu ích khi lỗi xảy ra ở chỗ hai dịch vụ giao nhau. Với unit của người dùng (systemctl --user) dùng journalctl --user -u tên.

Log theo thời gian thực: journalctl -f

sudo journalctl -u nginx -f

Đây là bản tương tự của tail -f: lệnh in 10 bản ghi gần nhất rồi chờ bản ghi mới. Rất tiện khi mở ở một terminal khác trong lúc khởi động lại dịch vụ hoặc tái hiện lỗi. Thoát bằng Ctrl+C.

Lọc theo thời gian và lần khởi động

Nếu biết sự cố xảy ra lúc nào, hãy lọc theo thời gian bằng --since và --until. Chúng nhận cả ngày giờ chính xác lẫn giá trị tương đối:

journalctl --since "2026-10-14 02:50" --until "2026-10-14 03:30"
journalctl --since "1 hour ago"
journalctl --since yesterday --until today
journalctl -u nginx --since "10 min ago"

Cách lọc hữu ích thứ hai là theo lần khởi động. Nếu máy chủ tự khởi động lại, nguyên nhân thường nằm ở cuối phiên trước đó:

$ journalctl --list-boots
 -2 8f1c...  Sat 2026-10-12 09:01:12 UTC  Sun 2026-10-13 22:47:03 UTC
 -1 a7d2...  Sun 2026-10-13 22:48:30 UTC  Tue 2026-10-14 03:05:51 UTC
  0 c3e9...  Tue 2026-10-14 03:07:02 UTC  Tue 2026-10-14 09:15:40 UTC

$ journalctl -b -1 -e      # cuối lần khởi động trước
$ journalctl -b            # chỉ lần khởi động hiện tại

Danh sách các lần khởi động chỉ có khi nhật ký được lưu trên đĩa. Cách bật điều này được trình bày ở phần cấu hình journald bên dưới.

Lọc theo mức độ quan trọng: journalctl -p

Mỗi bản ghi có mức ưu tiên syslog từ 0 đến 7. Tùy chọn -p hiển thị mức đã chọn và những mức quan trọng hơn:

MãTênKhi nào dùng
0emerghệ thống không hoạt động được
1alertcần can thiệp ngay lập tức
2critlỗi nghiêm trọng
3errlỗi
4warningcảnh báo
5noticesự kiện đáng chú ý nhưng bình thường
6infothông tin
7debuggỡ lỗi
journalctl -p err -b              # mọi lỗi từ lần khởi động hiện tại
journalctl -p warning..err -u ssh # khoảng mức cho một dịch vụ

Lệnh journalctl -p err -b là bước kiểm tra đầu tiên tốt sau khi khởi động lại hoặc cập nhật: trong vài giây nó cho thấy điều gì đã trục trặc.

Tìm kiếm và các bộ lọc khác

journald lưu các trường có cấu trúc cho từng bản ghi, và có thể lọc theo chúng mà không cần grep:

journalctl _PID=1834                 # theo số hiệu tiến trình
journalctl _COMM=sshd                # theo tên chương trình
journalctl _UID=1000                 # theo người dùng
journalctl /usr/sbin/sshd            # theo đường dẫn file thực thi
journalctl -k                        # chỉ thông báo của kernel (như dmesg)
journalctl -t CRON                   # theo định danh syslog
journalctl -g "Out of memory"        # tìm theo nội dung, biểu thức chính quy

Tùy chọn -g (--grep) xuất hiện từ systemd 237; trên hệ thống cũ hơn dùng pipeline thông thường journalctl --no-pager | grep .... Các bộ lọc theo nhiều trường được kết hợp theo kiểu «VÀ», nên journalctl -u nginx -p err --since today chỉ trả về lỗi nginx trong ngày hôm nay.

Định dạng đầu ra

Tùy chọn -o đổi định dạng. Các lựa chọn hữu ích nhất:

  • -o short-iso — thời gian theo chuẩn ISO 8601, dễ so sánh với log của ứng dụng.
  • -o verbose — mọi trường của bản ghi, gồm _SYSTEMD_UNIT, _PID, _BOOT_ID.
  • -o json hoặc json-pretty — để script hoặc jq xử lý.
  • -o cat — chỉ nội dung thông báo, không có ngày giờ và tên máy.
journalctl -u myapp -o json --since today | jq -r '.MESSAGE'

Cấu hình journald: lưu trữ và dung lượng

Cấu hình nằm trong /etc/systemd/journald.conf (nên đặt phần ghi đè trong /etc/systemd/journald.conf.d/*.conf). Tham số chính là Storage:

  • persistent — ghi log xuống đĩa tại /var/log/journal và giữ lại sau khi khởi động lại.
  • volatile — chỉ trong bộ nhớ, tại /run/log/journal.
  • auto (mặc định) — ghi xuống đĩa nếu thư mục /var/log/journal tồn tại.

Trên một số image tối giản không có thư mục này, và sau khi khởi động lại lịch sử sẽ mất. Để bật lưu trữ lâu dài:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

Để nhật ký không chiếm toàn bộ đĩa, đặt giới hạn:

# /etc/systemd/journald.conf.d/size.conf
[Journal]
Storage=persistent
SystemMaxUse=500M
MaxRetentionSec=1month

Mặc định SystemMaxUse bằng 10% dung lượng hệ thống tệp, nhưng không quá 4 GB.

Cách dọn nhật ký journalctl

$ journalctl --disk-usage
Archived and active journals take up 1.8G in the file system.

sudo journalctl --vacuum-size=300M   # giữ không quá 300 MB
sudo journalctl --vacuum-time=2weeks # xóa bản ghi cũ hơn hai tuần
sudo journalctl --rotate             # đóng các file đang ghi để có thể xóa cả chúng

Không nên xóa file trong /var/log/journal bằng rm: vacuum làm đúng việc đó một cách an toàn và không đụng tới file đang được ghi.

rsyslog: log văn bản truyền thống

rsyslog là daemon nhận các thông điệp syslog (kể cả những thông điệp được chuyển từ journald) và phân loại chúng vào các file theo quy tắc. Cấu hình nằm trong /etc/rsyslog.conf và /etc/rsyslog.d/*.conf. Một quy tắc gồm bộ chọn nguồn.mức và hành động:

# /etc/rsyslog.d/50-default.conf (đoạn trích)
auth,authpriv.*        /var/log/auth.log
*.*;auth,authpriv.none -/var/log/syslog
kern.*                 -/var/log/kern.log

Dấu trừ trước đường dẫn nghĩa là ghi không đồng bộ xuống đĩa sau mỗi dòng — nhanh hơn, nhưng khi có sự cố vài dòng cuối có thể bị mất. Sau khi sửa cấu hình, kiểm tra cú pháp và khởi động lại dịch vụ:

sudo rsyslogd -N1
sudo systemctl restart rsyslog

Lý do chính để giữ rsyslog bên cạnh journald là chuyển tiếp log về máy chủ tập trung. Một dòng sau đây gửi mọi thứ qua TCP:

# /etc/rsyslog.d/90-remote.conf
*.* @@logs.example.com:514

Một ký tự @ nghĩa là UDP, hai ký tự @@ là TCP. Nếu máy chủ chính hỏng hoàn toàn, bản sao log vẫn còn trên máy khác. Để ghi thông điệp của riêng mình vào nhật ký hệ thống từ script, dùng logger:

logger -t backup -p user.err "Sao lưu cơ sở dữ liệu thất bại"
journalctl -t backup -n 5

logrotate: xoay vòng log

Các file log dạng văn bản lớn lên mãi cho đến khi ai đó cắt bớt. Việc này do logrotate đảm nhận: mỗi ngày (qua cron hoặc timer logrotate.timer), nó đổi tên file hiện tại, nén các file cũ và xóa những file xa nhất. Cấu hình chung ở /etc/logrotate.conf, quy tắc cho từng chương trình ở /etc/logrotate.d/.

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 myapp adm
    postrotate
        systemctl reload myapp > /dev/null 2>&1 || true
    endscript
}
Chỉ thịÝ nghĩa
daily / weekly / size 100Mkhi nào xoay vòng
rotate 14

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

Vì sao journalctl chỉ hiển thị bản ghi từ lần khởi động gần nhất?

Nhật ký đang được lưu trong bộ nhớ (/run/log/journal). Hãy tạo thư mục /var/log/journal hoặc đặt Storage=persistent trong journald.conf, rồi khởi động lại systemd-journald.

Làm sao cho người dùng thường đọc log hệ thống mà không cần sudo?

Thêm người dùng vào nhóm systemd-journal (hoặc adm trên Debian và Ubuntu): sudo usermod -aG systemd-journal tên-người-dùng, sau đó đăng nhập lại.

Có thể xem nhật ký của một hệ thống khác, ví dụ từ ổ đĩa đã gắn không?

Có, chỉ định thư mục journal bằng -D: journalctl -D /mnt/var/log/journal. Tùy chọn --file đọc một file .journal riêng lẻ.

Có cần rsyslog khi đã có journald không?

Không bắt buộc. Nó hữu ích khi cần file văn bản cho các công cụ cũ hoặc chuyển log về máy chủ tập trung; trên nhiều image tối giản người ta không cài nó nữa.

Làm sao xuất log của một dịch vụ ra file để gửi cho đồng nghiệp?

Chạy journalctl -u tên --since today --no-pager > service.log — kết quả là một file văn bản thông thường.

Học chủ đề này qua video

Chủ đề này được giảng chi tiết kèm thực hành trong khóa học “Linux: с нуля до уверенного администрирования”.

Đến khóa học