systemd: là gì, hoạt động ra sao và cách quản lý dịch vụ trong Linux
systemd là hệ thống khởi tạo và trình quản lý dịch vụ của Linux: kernel khởi chạy nó như tiến trình đầu tiên (PID 1), nó bật các dịch vụ còn lại theo đúng thứ tự và theo dõi chúng. Mọi thứ systemd làm đều được mô tả bằng unit — mô tả văn bản của dịch vụ, timer, điểm gắn; systemctl khởi động, dừng và bật tự khởi động chúng, còn journalctl hiển thị nhật ký.
systemd là hệ thống khởi tạo và trình quản lý dịch vụ được dùng trong đa số bản phân phối Linux hiện đại: Debian, Ubuntu, Fedora, RHEL và các bản dẫn xuất. Sau khi tải xong, kernel khởi chạy systemd như tiến trình đầu tiên với PID 1, rồi systemd bật mạng, gắn ổ đĩa, khởi động web server, cơ sở dữ liệu và mọi thứ còn lại. Nói ngắn gọn, systemd là "bộ điều phối" biết dịch vụ nào phải chạy, khởi động theo thứ tự nào và phải làm gì khi một dịch vụ bị lỗi.
Kiểm tra xem hệ thống có dùng systemd không rất đơn giản:
$ ps -p 1 -o comm=
systemd
Vì sao cần systemd
Trước đây Linux dùng SysV init: một tập các script shell trong /etc/init.d/ được chạy lần lượt. Cách này dễ hiểu nhưng chậm và dễ hỏng. Mỗi script tự ghi tệp PID, tự quyết định cách kiểm tra tiến trình còn sống không, và việc tự khởi động lại dịch vụ bị lỗi phải tự viết thêm.
systemd giải quyết các vấn đề này theo cách tập trung:
- Khởi động song song. Các dịch vụ không phụ thuộc nhau được khởi động cùng lúc, nên máy khởi động nhanh hơn.
- Phụ thuộc và thứ tự. Mô tả dịch vụ nêu rõ nó cần gì (ví dụ mạng) và phải chạy sau cái gì.
- Giám sát. systemd biết mọi tiến trình của dịch vụ nhờ cgroups và có thể khởi động lại dịch vụ khi lỗi.
- Nhật ký thống nhất. Đầu ra của mọi dịch vụ được journald thu thập, và đọc nhật ký bằng một lệnh.
- Giao diện thống nhất. Mọi dịch vụ quản lý giống nhau:
systemctl start|stop|restart|status.
Ngoài trình quản lý dịch vụ, dự án systemd còn có các thành phần: journald (nhật ký), logind (phiên người dùng), timesyncd (đồng bộ thời gian), resolved (DNS), networkd (mạng). Không phải bản phân phối nào cũng dùng tất cả, nhưng systemd làm PID 1 và journald thì gần như có ở mọi nơi.
Unit: systemd được cấu thành từ gì
Mọi thứ systemd quản lý đều được mô tả bằng unit. Unit là một tệp văn bản theo định dạng INI, loại unit được xác định bởi đuôi tệp.
| Loại | Đuôi | Mô tả |
|---|---|---|
| service | .service | dịch vụ — tiến trình daemon hoặc tác vụ một lần |
| timer | .timer | chạy một unit khác theo lịch (thay thế cron) |
| socket | .socket | socket mà khi có kết nối thì dịch vụ được khởi động |
| target | .target | nhóm unit, "trạng thái của hệ thống" (ví dụ multi-user.target) |
| mount | .mount | điểm gắn ổ đĩa |
| path | .path | theo dõi một tệp hoặc thư mục |
Tệp unit nằm ở đâu
Tệp unit được lưu ở nhiều thư mục, và chúng có thứ tự ưu tiên:
/usr/lib/systemd/system/(trên Debian và Ubuntu cũng có/lib/systemd/system/) — unit do gói cài đặt. Không nên sửa trực tiếp: cập nhật gói sẽ ghi đè thay đổi./etc/systemd/system/— unit và cấu hình ghi đè của quản trị viên. Ưu tiên cao nhất./run/systemd/system/— unit tạm thời tạo trong lúc hệ thống đang chạy.
Để xem nội dung cuối cùng của một unit cùng mọi ghi đè, dùng systemctl cat nginx.service.
Target thay cho runlevel
Các runlevel cũ đã được thay bằng target. multi-user.target là chế độ máy chủ thông thường không có giao diện đồ họa, graphical.target có giao diện đồ họa, rescue.target là chế độ khôi phục một người dùng. Target mặc định hiển thị bằng systemctl get-default, đổi bằng systemctl set-default multi-user.target.
systemctl: quản lý dịch vụ
systemctl là công cụ chính để làm việc với systemd. Hầu hết lệnh thay đổi trạng thái hệ thống và cần sudo.
| Lệnh | Tác dụng |
|---|---|
systemctl status nginx | trạng thái dịch vụ, PID, bộ nhớ, các dòng nhật ký gần nhất |
systemctl start nginx | khởi động ngay |
systemctl stop nginx | dừng |
systemctl restart nginx | khởi động lại (stop + start) |
systemctl reload nginx | tải lại cấu hình mà không dừng (nếu dịch vụ hỗ trợ) |
systemctl enable nginx | bật tự khởi động cùng hệ thống |
systemctl disable nginx | tắt tự khởi động |
systemctl enable --now nginx | bật tự khởi động và chạy ngay |
systemctl is-active nginx | in ra active/inactive — tiện trong script |
systemctl list-units --type=service | các dịch vụ đã nạp |
systemctl --failed | các unit bị lỗi |
systemctl daemon-reload | đọc lại tệp unit sau khi sửa |
Đọc systemctl status thế nào
$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-10-12 09:14:03 UTC; 2h 5min ago
Docs: man:nginx(8)
Main PID: 812 (nginx)
Tasks: 3 (limit: 2307)
Memory: 6.1M
CPU: 154ms
CGroup: /system.slice/nginx.service
├─812 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
├─813 "nginx: worker process"
└─814 "nginx: worker process"
Dòng Loaded cho biết tệp unit lấy từ đâu và tự khởi động có bật hay không (enabled). Dòng Active là trạng thái hiện tại: active (running), inactive (dead) hoặc failed. Khối CGroup liệt kê mọi tiến trình của dịch vụ — chính nhờ đó systemd biết tiến trình nào thuộc về dịch vụ.
enable khác start ở điểm nào
Đây là chỗ hay nhầm lẫn. start chạy dịch vụ ngay bây giờ, nhưng sau khi khởi động lại máy nó sẽ không tự chạy. enable tạo liên kết mềm trong thư mục của target (ví dụ /etc/systemd/system/multi-user.target.wants/), nhờ đó dịch vụ khởi động cùng hệ thống, nhưng lúc này nó chưa chạy. Thường cần cả hai — dùng enable --now.
Còn trạng thái thứ ba là mask. systemctl mask service liên kết unit với /dev/null, và không thể chạy nó bằng tay hay như phụ thuộc. Hữu ích khi cần chắc chắn dịch vụ bị tắt hẳn.
journalctl: nhật ký dịch vụ
Mọi thứ dịch vụ ghi ra stdout và stderr đều được systemd-journald thu lại và lưu vào nhật ký nhị phân cùng siêu dữ liệu: tên unit, PID, mức độ, thời gian. Đọc nhật ký bằng journalctl.
journalctl -u nginx # nhật ký của một dịch vụ
journalctl -u nginx -f # theo dõi theo thời gian thực, như tail -f
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx -n 50 # 50 dòng gần nhất
journalctl -b # từ lần khởi động hiện tại
journalctl -b -1 # lần khởi động trước
journalctl -p err -b # chỉ lỗi trở lên nghiêm trọng
journalctl -k # thông điệp của kernel
journalctl --disk-usage # nhật ký chiếm bao nhiêu dung lượng
Tùy chọn -p lọc theo mức ưu tiên của syslog: emerg, alert, crit, err, warning, notice, info, debug. Mức được chỉ định bao gồm cả mọi mức nghiêm trọng hơn.
Nhật ký sau khi khởi động lại
Nếu thư mục /var/log/journal không tồn tại và /etc/systemd/journald.conf có Storage=auto, nhật ký chỉ được giữ trong bộ nhớ (/run/log/journal) và mất khi khởi động lại. Để giữ lâu dài, đặt Storage=persistent hoặc tạo thư mục rồi khởi động lại journald. Dung lượng giới hạn bởi tham số SystemMaxUse=, còn dọn nhật ký cũ bằng journalctl --vacuum-time=2weeks hoặc --vacuum-size=500M.
journald thường đi kèm rsyslog: journald chuyển thông điệp cho rsyslog, còn rsyslog ghi các tệp văn bản truyền thống vào /var/log/ và có thể gửi nhật ký tới máy chủ tập trung.
Tự khởi động dịch vụ của riêng bạn: ví dụ unit-file
Giả sử bạn có một ứng dụng — script hoặc file nhị phân — cần chạy liên tục, tự khởi động khi bật máy và tự chạy lại khi bị lỗi. Tạo tệp /etc/systemd/system/myapp.service:
[Unit]
Description=My web application
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/env
ExecStart=/opt/myapp/bin/server --port 8080
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Phân tích các phần:
- [Unit] — mô tả và phụ thuộc.
After=chỉ đặt thứ tự,Wants=là phụ thuộc mềm (kéo unit lên nhưng không lỗi nếu nó không khởi động được). Phụ thuộc cứng làRequires=. - [Service] — cách chạy.
Type=simplenghĩa là tiến trình trongExecStartchính là dịch vụ và không tự chuyển ra nền.User=chạy bằng người dùng không có đặc quyền.Restart=on-failurekhởi động lại dịch vụ nếu nó thoát với lỗi, sauRestartSecgiây. - [Install] — việc
enablesẽ làm.WantedBy=multi-user.targetnghĩa là "chạy khi khởi động thông thường".
Áp dụng:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp
journalctl -u myapp -f
Lỗi thường gặp trong unit-file
- Đường dẫn tương đối trong ExecStart. Đường dẫn tới chương trình phải là tuyệt đối. systemd không tìm lệnh trong
PATHcủa người dùng như shell vẫn làm. - Quên daemon-reload. Sau khi sửa tệp, systemd vẫn dùng bản cũ và cảnh báo về điều này trong
status. - Daemon tự chuyển ra nền. Nếu chương trình tự fork nhưng lại khai báo
Type=simple, systemd sẽ nghĩ dịch vụ đã kết thúc. Hoặc chạy chương trình ở chế độ foreground, hoặc dùngType=forkingcùngPIDFile=. - Biến môi trường từ profile. Dịch vụ không đọc
~/.bashrcvà/etc/profile. Biến được đặt quaEnvironment=hoặcEnvironmentFile=.
Ghi đè mà không sửa unit của gói
Để thay đổi tham số của dịch vụ do gói cung cấp mà không sửa tệp của nó, dùng drop-in:
sudo systemctl edit nginx
Trình soạn thảo sẽ mở ra, và thay đổi được lưu vào /etc/systemd/system/nginx.service.d/override.conf. Ví dụ bạn có thể thêm [Service] và Restart=always. Khi thoát khỏi trình soạn thảo, systemd tự đọc lại cấu hình.
Timer systemd thay cho cron
Timer là unit chạy dịch vụ cùng tên theo lịch. So với cron, ưu điểm là nhật ký của tác vụ nằm trong journal, có thể khai báo phụ thuộc, và các lần chạy bị bỏ lỡ có thể được bù (Persistent=true). Ví dụ sao lưu hằng ngày:
# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers
Kiểm tra biểu thức OnCalendar bằng systemd-analyze calendar "*-*-* 03:00:00" — lệnh sẽ cho biết lần chạy tiếp theo là khi nào.
Chẩn đoán thời gian khởi động
systemd lưu thời điểm khởi động của từng unit, nên rất dễ tìm nguyên nhân khi máy khởi động chậm:
systemd-analyze # tổng thời gian khởi động
systemd-analyze blame # các unit, sắp xếp theo thời gian khởi động
systemd-analyze critical-chain # chuỗi làm chậm quá trình khởi động
systemd-analyze verify /etc/systemd/system/myapp.service # kiểm tra unit-file
Tóm lại
systemd là PID 1 và trình quản lý dịch vụ của Linux hiện đại. Nó mô tả mọi thứ bằng unit, được điều khiển bằng systemctl, thu thập nhật ký vào journal mà journalctl đọc, và có thể chạy tác vụ bằng timer thay cho cron. Để dùng thành thạo, chỉ cần nắm status, enable --now, journalctl -u và viết được một unit-file đơn giản với Restart=on-failure. systemd, journald và ghi nhật ký đều được thực hành trong khóa học Linux.
Câu hỏi thường gặp
Làm sao biết hệ thống của mình có dùng systemd không?
Chạy ps -p 1 -o comm= — nếu kết quả là systemd, hệ thống đang chạy dưới systemd. Ngoài ra, thư mục /run/systemd/system chỉ tồn tại khi máy được khởi động bằng systemd.
systemctl restart khác reload ở điểm nào?
restart dừng hẳn rồi khởi động lại dịch vụ, các kết nối đang mở bị ngắt. reload yêu cầu dịch vụ đọc lại cấu hình mà không dừng, nhưng chỉ hoạt động nếu unit có khai báo ExecReload.
Có thể chạy dịch vụ systemd bằng người dùng thường mà không cần sudo không?
Có, systemd có thể chạy theo người dùng: đặt unit trong ~/.config/systemd/user/ và quản lý bằng systemctl --user. Để chúng chạy khi không có phiên đăng nhập, bật loginctl enable-linger cho người dùng đó.
Vì sao dịch vụ ở trạng thái failed và làm sao xóa trạng thái đó?
Tìm nguyên nhân trong journalctl -u tên -b và dòng Active trong lệnh status. Sau khi sửa, khởi động lại dịch vụ; còn để xóa dấu failed mà không cần khởi động lại, dùng systemctl reset-failed.
Nhật ký systemd được lưu ở đâu trên đĩa?
Nếu bật lưu lâu dài thì ở /var/log/journal/, ở dạng nhị phân; nếu không thì ở /run/log/journal/ trong bộ nhớ. Đọc bằng journalctl, không dùng các công cụ xử lý văn bản.
Chủ đề này được giảng chi tiết kèm thực hành trong khóa học “Linux: с нуля до уверенного администрирования”.
- systemd: как на самом деле запускаются сервисы в современном Linux
- Журналы и мониторинг: journald, rsyslog и sysstat