Trong các bản phân phối Linux hiện đại (Ubuntu, Debian, CentOS, RHEL, Rocky Linux), Systemd là phần mềm đầu tiên được Kernel khởi chạy trong không gian người dùng, mang mã tiến trình đặc biệt: PID 1.
Nó không đơn thuần là một trình khởi động dịch vụ (Init System) thay thế cho SysV init cũ kỹ, mà là một nền tảng điều phối hệ thống hoàn chỉnh: quản lý vòng đời tiến trình, theo dõi trạng thái, giới hạn tài nguyên thông qua Linux cgroups, gom log tập trung qua Journald và lập lịch tác vụ thay thế Cron.
🎯 Góc Nhìn Chuyên Gia: Vì Sao Systemd Thống Trị?
Trước khi Systemd ra đời, SysV init sử dụng các đoạn bash script cồng kềnh trong /etc/init.d/, khởi động từng dịch vụ một cách tuần tự (rất chậm), không có khả năng giám sát tiến trình con và không có cơ chế giới hạn CPU/RAM tích hợp.
Systemd giải quyết triệt để các nhược điểm này bằng:
- Khởi động song song tối đa (Parallel Execution): Khởi chạy các dịch vụ đồng thời dựa trên cơ chế Socket Activation và D-Bus.
- Theo dõi tiến trình qua cgroups: Mọi tiến trình con do dịch vụ sinh ra đều được gom vào một nhóm cgroup. Khi bạn ra lệnh dừng một dịch vụ, Systemd sẽ dọn dẹp sạch sẽ toàn bộ các tiến trình con liên quan, triệt tiêu hoàn toàn tiến trình mồ côi (Orphan process).
- Khai báo dạng Declarative: Định nghĩa dịch vụ bằng file cấu hình phẳng (
.iniformat) thay vì hàng trăm dòng shell script phức tạp.
1. Kiến Trúc Systemd & Các Loại Unit
Trong Systemd, mọi thực thể được quản lý đều gọi là một Unit. Đuôi mở rộng của file biểu thị loại Unit:
| Loại Unit | Đuôi mở rộng | Mục đích & Ứng dụng |
|---|---|---|
| Service | .service | Quản lý daemon, ứng dụng nền (Nginx, Docker, Node.js, Go backend) |
| Target | .target | Nhóm các Unit lại với nhau để tạo trạng thái hệ thống (tương đương Runlevel) |
| Timer | .timer | Lập lịch kích hoạt Service theo thời gian (giải pháp hiện đại thay thế Cron) |
| Socket | .socket | Lắng nghe kết nối mạng/IPC, chỉ khởi động Service khi có request đến |
| Mount | .mount | Quản lý điểm gắn kết hệ thống tệp tin (thay thế hoặc bổ trợ cho /etc/fstab) |
| Slice | .slice | Phân cấp và giới hạn tài nguyên CPU/RAM/IO qua cgroups |
Vị trí lưu trữ Unit file & Thứ tự ưu tiên
Khi nạp một Unit, Systemd sẽ tìm kiếm theo thứ tự ưu tiên từ cao xuống thấp:
/etc/systemd/system/(Ưu tiên cao nhất): Nơi chứa cấu hình do Quản trị viên hệ thống (SysAdmin/SRE) tự tạo hoặc tùy biến./run/systemd/system/: Cấu hình tạm thời được tạo trong lúc hệ thống đang chạy (mất sau khi reboot)./lib/systemd/system/(hoặc/usr/lib/systemd/system/): Cấu hình mặc định do gói phần mềm (apt, yum, dnf) cài đặt.
[!WARNING] Không bao giờ sửa trực tiếp file trong
/lib/systemd/system/! Khi gói phần mềm được cập nhật (update/upgrade), thay đổi của bạn sẽ bị ghi đè và biến mất. Luôn đặt file tùy biến trong/etc/systemd/system/hoặc sử dụng cơ chế Drop-in override (systemctl edit).
2. Viết File .service Chuẩn Vận Hành Production
Dưới đây là một Service Unit mẫu cho ứng dụng Backend (Node.js, Go, Python hoặc Java), tích hợp đầy đủ tính năng: Tự phục hồi, Bảo mật phân quyền và Giới hạn tài nguyên cgroups:
# /etc/systemd/system/my-api.service
[Unit]
Description=My CloudNative Backend API Service
Documentation=https://docs.cloudnative.vn/api
# Chỉ khởi động sau khi mạng đã sẵn sàng
After=network.target network-online.target
Wants=network-online.target
[Service]
# Loại tiến trình: simple phù hợp với ứng dụng chạy foreground
Type=simple
# Phân quyền: TUYỆT ĐỐI KHÔNG CHẠY BẰNG ROOT TRÊN PRODUCTION
User=appuser
Group=appgroup
# Thư mục làm việc & Lệnh thực thi
WorkingDirectory=/opt/my-api
ExecStart=/usr/bin/node /opt/my-api/server.js
ExecReload=/bin/kill -HUP $MAINPID
# Biến môi trường
Environment="NODE_ENV=production" "PORT=3000"
EnvironmentFile=-/etc/default/my-api
# --- CƠ CHẾ TỰ ĐỘNG PHỤC HỒI (RESTART POLICY) ---
# Tự động bật lại khi ứng dụng bị crash
Restart=always
RestartSec=5s
# Chống vòng lặp khởi động vô tận (Crash Loop): nếu crash quá 5 lần trong 60s thì dừng hẳn
StartLimitIntervalSec=60s
StartLimitBurst=5
# --- BẢO MẬT & SANDBOXING ---
# Ngăn chặn tiến trình con leo thang đặc quyền (Privilege Escalation)
NoNewPrivileges=true
# Khóa hệ thống file hệ thống ở chế độ chỉ đọc đối với service này
ProtectSystem=strict
# Không cho phép service đọc/ghi vào thư mục /home của người dùng khác
ProtectHome=true
# Cấp một thư mục /tmp riêng biệt, cô lập với hệ thống
PrivateTmp=true
# Cho phép ghi vào thư mục log và dữ liệu cần thiết
ReadWritePaths=/var/log/my-api /var/lib/my-api
# --- GIỚI HẠN TÀI NGUYÊN (CGROUPS INTEGRATION) ---
# Giới hạn dung lượng RAM tối đa 2GB (Vượt quá ngưỡng sẽ bị OOM Kill service này)
MemoryMax=2G
# Giới hạn sử dụng tối đa 1.5 CPU Cores (150%)
CPUQuota=150%
[Install]
# Đăng ký khởi động cùng hệ điều hành ở chế độ đa người dùng
WantedBy=multi-user.target
3. Làm Chủ Lệnh systemctl
systemctl là công cụ dòng lệnh duy nhất bạn cần để kiểm soát mọi trạng thái dịch vụ trong Systemd.
3.1. Các thao tác vòng đời cơ bản
# Khởi động, dừng và khởi động lại dịch vụ
sudo systemctl start my-api
sudo systemctl stop my-api
sudo systemctl restart my-api
# Nạp lại cấu hình ứng dụng mà không ngắt kết nối đang chạy (Graceful Reload)
sudo systemctl reload my-api
# Bật/Tắt chế độ tự khởi động cùng hệ thống khi reboot
sudo systemctl enable my-api
sudo systemctl disable my-api
# Bật tự khởi động và chạy ngay lập tức trong 1 lệnh duy nhất
sudo systemctl enable --now my-api
3.2. Cú pháp sống còn: daemon-reload
[!IMPORTANT] Bất cứ khi nào bạn tạo mới, chỉnh sửa hoặc xóa một file Unit trong
/etc/systemd/system/, bạn BẮT BUỘC phải chạy lệnh:sudo systemctl daemon-reloadLệnh này yêu cầu tiến trình PID 1 quét lại toàn bộ ổ cứng và nạp lại đồ thị phụ thuộc (dependency tree). Nếu quên lệnh này, Systemd sẽ tiếp tục chạy cấu hình cũ đang lưu trong bộ nhớ RAM.
3.3. Bắt trạng thái trong Script & Tự động hóa
# Kiểm tra dịch vụ có đang chạy hay không (trả về exit code 0 nếu active)
systemctl is-active --quiet my-api && echo "Dịch vụ đang hoạt động mượt mà"
# Kiểm tra dịch vụ có được bật khởi động cùng OS không
systemctl is-enabled --quiet my-api
# Liệt kê tất cả các dịch vụ đang ở trạng thái lỗi (FAILED) trên toàn server
systemctl list-units --type=service --state=failed
3.4. Ghi đè cấu hình an toàn bằng Drop-in (override.conf)
Thay vì sao chép toàn bộ file unit của bên thứ ba (như Docker, Nginx) ra /etc/systemd/system/, hãy dùng lệnh:
sudo systemctl edit docker.service
Systemd sẽ mở trình soạn thảo và tạo file /etc/systemd/system/docker.service.d/override.conf. Tại đây, bạn chỉ cần ghi những dòng bạn muốn ghi đè (ví dụ thêm cờ mở rộng hoặc tăng LimitNOFILE). Khi Docker nâng cấp phiên bản, cấu hình ghi đè của bạn vẫn được giữ nguyên an toàn!
4. Phân Tích Log Dịch Vụ Với journalctl
Mọi thứ mà dịch vụ của bạn in ra màn hình (stdout và stderr) đều được Systemd gom tự động vào Journald. Không còn cảnh ứng dụng crash mất dấu vết vì chưa kịp ghi ra file log!
# 1. Theo dõi log thời gian thực giống 'tail -f'
journalctl -u my-api -f
# 2. Xem 100 dòng log gần nhất không bị ngắt trang (no-pager)
journalctl -u my-api -n 100 --no-pager
# 3. Lọc log trong một khoảng thời gian cụ thể (rất hữu ích khi điều tra sự cố)
journalctl -u my-api --since "2026-10-10 14:00:00" --until "2026-10-10 14:30:00"
journalctl -u my-api --since "15 minutes ago"
# 4. Chỉ hiển thị log lỗi nghiêm trọng (từ mức Error trở lên)
journalctl -u my-api -p err..emerg
# 5. Xem toàn bộ log của hệ thống kể từ lần khởi động gần nhất (Current Boot)
journalctl -b
Giới hạn dung lượng Journald tránh đầy ổ đĩa
Mặc định, Journald có thể chiếm tới 10% dung lượng phân vùng root. Để cấu hình giới hạn cố định:
# Sửa file /etc/systemd/journald.conf:
[Journal]
Storage=persistent
# Giới hạn dung lượng tối đa 1GB
SystemMaxUse=1G
# Giữ log tối đa trong 14 ngày
MaxRetentionSec=14day
# Khởi động lại service journald và dọn sạch log cũ ngay lập tức
sudo systemctl restart systemd-journald
sudo journalctl --vacuum-size=1G
sudo journalctl --vacuum-time=14d
5. Thay Thế Cron Bằng Systemd Timer (.timer)
Tại sao các kỹ sư SRE hiện đại dần thay thế Cronjob truyền thống bằng Systemd Timer?
- Độ tin cậy: Có thể đặt ràng buộc (chỉ chạy backup khi dịch vụ database đang active).
- Quản lý Log: Toàn bộ output của tác vụ tự động được lưu vào
journalctlcó timestamp chuẩn xác. - Giới hạn tài nguyên: Tác vụ chạy định kỳ có thể bị khống chế RAM/CPU để không làm ảnh hưởng đến ứng dụng chính.
- Quan sát lịch trình: Xem thời điểm chạy tiếp theo dễ dàng qua
systemctl list-timers.
Cách tạo một Systemd Timer chạy định kỳ
Mỗi timer gồm 2 file cùng tên: một file .service để định nghĩa lệnh cần chạy, và một file .timer để định nghĩa thời gian chạy.
Bước 1: Tạo file Service thực thi tác vụ (Type=oneshot)
# /etc/systemd/system/db-backup.service
[Unit]
Description=Database Daily Backup Task
[Service]
Type=oneshot
User=postgres
ExecStart=/opt/scripts/backup-db.sh
Bước 2: Tạo file Timer định nghĩa lịch chạy
# /etc/systemd/system/db-backup.timer
[Unit]
Description=Run DB Backup every night at 02:00 AM
[Timer]
# Chạy vào đúng 02:00 sáng mỗi ngày
OnCalendar=*-*-* 02:00:00
# Tránh tình trạng server bị tắt lúc 2h sáng: khi bật lại sẽ chạy bù ngay lập tức
Persistent=true
[Install]
WantedBy=timers.target
Bước 3: Kích hoạt Timer
sudo systemctl daemon-reload
sudo systemctl enable --now db-backup.timer
# Xem danh sách toàn bộ các Timer đang hoạt động và thời gian chạy kế tiếp
systemctl list-timers
⚡ Bảng Bắt Bệnh Nhanh Khi Dịch Vụ Không Thể Khởi Động
| Triệu chứng | Nguyên nhân cốt lõi | Cách xử lý |
|---|---|---|
Active: failed (Result: exit-code) | Ứng dụng bị lỗi cú pháp, thiếu biến môi trường hoặc port bị trùng | Chạy journalctl -u <service> -n 50 --no-pager để đọc chính xác stack trace |
Active: failed (Result: start-limit-hit) | Dịch vụ bị crash liên tục vượt quá ngưỡng StartLimitBurst | Sửa tận gốc lỗi ứng dụng, sau đó chạy systemctl reset-failed <service> rồi start lại |
status=203/EXEC | Không tìm thấy file ExecStart hoặc file chưa được cấp quyền chmod +x | Kiểm tra lại đường dẫn tuyệt đối trong file .service |
status=217/USER | User hoặc Group khai báo trong file unit không tồn tại trên hệ thống | Kiểm tra id <username> hoặc tạo user bằng useradd -r -s /bin/false <username> |
| Dịch vụ biến mất sau reboot | Quên chưa bật tự khởi động | Chạy sudo systemctl enable <service> |
Bài tiếp theo đề xuất: Gỡ Lỗi & Giám Sát Hiệu Năng – Bắt bệnh nghẽn cổ chai CPU, Memory, Disk I/O và Network bằng các công cụ chuyên sâu vmstat, iostat, sar và bpftrace.