Ngừng thăm dò, bắt đầu phản ứng
Tôi từng dựa vào Cron để xử lý các file đầu vào, nhưng đó là một giải pháp khá vụng về. Cứ mỗi 60 giây, một script lại thức dậy, quét thư mục để tìm dữ liệu mới rồi lại đi ngủ. Nó vẫn chạy được, nhưng cảm giác rất chậm chạp. Nếu một file xuất hiện vào lúc 12:00:01, nó phải nằm chờ tới 59 giây. Tệ hơn nữa, nếu thư mục trống, script vẫn chạy, gây tốn tài nguyên CPU và làm rối nhật ký (logs) một cách vô ích.
Systemd Path unit đã thay đổi điều đó. Thay vì hỏi “Có gì mới không?” mỗi phút, hệ thống sẽ thông báo cho bạn ngay khi có sự kiện xảy ra. Trên một máy chủ Ubuntu 22.04 tiêu chuẩn với 4GB RAM, việc chuyển từ Cron sang Path unit đã làm giảm mức sử dụng CPU cơ bản trong thời gian nghỉ. Vì Path unit sử dụng hệ thống con inotify của nhân Linux, chúng tiêu tốn chưa đến 1MB bộ nhớ trong khi chờ đợi hoạt động. Bạn không cần cài đặt thêm các công cụ như incron; nó đã được tích hợp sẵn trong hệ điều hành của bạn.
Bắt đầu nhanh: Thiết lập trong 5 phút
Để bộ kích hoạt (trigger) hoạt động, bạn cần hai file cụ thể: một unit .path để giám sát mục tiêu và một unit .service để thực thi script. Hãy cùng thiết lập giám sát cho một file có tên là /tmp/trigger.txt.
1. Tạo Service Unit
Service xác định hành động sẽ thực hiện. Hãy tạo file /etc/systemd/system/task-runner.service và dán cấu hình sau:
[Unit]
Description=Thực thi script khi file thay đổi
[Service]
Type=oneshot
ExecStart=/usr/local/bin/my-script.sh
2. Tạo Path Unit
File này cho Systemd biết cần theo dõi cái gì. Để liên kết tự động hoạt động, nó phải có cùng tên tệp cơ sở (base name) với service của bạn. Tạo file /etc/systemd/system/task-runner.path:
[Unit]
Description=Theo dõi thay đổi tại /tmp/trigger.txt
[Path]
PathModified=/tmp/trigger.txt
[Install]
WantedBy=multi-user.target
3. Kích hoạt bộ giám sát
Tải lại trình quản lý hệ thống và kích hoạt path unit. Hãy nhớ: bạn cần khởi chạy path unit, không phải service.
sudo systemctl daemon-reload
sudo systemctl enable --now task-runner.path
Giờ đây, ngay khi bạn chạy lệnh echo "data" >> /tmp/trigger.txt, Systemd sẽ kích hoạt script ngay lập tức.
Lựa chọn bộ kích hoạt phù hợp
Systemd cung cấp nhiều cách để giám sát hoạt động của file. Chọn sai loại là một sai lầm phổ biến của những người mới bắt đầu. Dưới đây là cách các chỉ thị khác nhau hoạt động trong môi trường thực tế:
- PathExists: Kích hoạt nếu file tồn tại. Nó không quan tâm file đó mới hay đã có từ lâu. Chỉ cần file hiện diện, service sẽ chạy.
- PathExistsGlob: Hoạt động giống như trên nhưng hỗ trợ ký tự đại diện (wildcards). Dùng cho các mẫu như
/uploads/*.pdf. - PathChanged: Chờ cho đến khi file được đóng sau khi ghi xong. Đây là lựa chọn an toàn nhất cho việc tải file (upload), đảm bảo quá trình ghi hoàn tất trước khi script xử lý dữ liệu.
- PathModified: Quyết liệt hơn. Nó kích hoạt ở bất kỳ thao tác ghi nào, ngay cả trước khi file được đóng. Tránh dùng cho các file lớn để ngăn script đọc phải dữ liệu chưa hoàn chỉnh.
- DirectoryNotEmpty: Dùng cho các “thư mục giám sát”. Nó kích hoạt ngay khi file đầu tiên xuất hiện trong một thư mục vốn đang trống.
Tôi nhận thấy rằng PathChanged hầu như luôn là lựa chọn tốt nhất cho các luồng xử lý dữ liệu (data pipelines). Nó cung cấp một vùng đệm tự nhiên giúp ngăn chặn tình trạng tranh chấp (race conditions) giữa tiến trình ghi và script của bạn.
Xử lý các sự kiện tần suất cao
Điều gì xảy ra nếu hàng trăm file đổ vào một thư mục cùng một lúc? Bạn có thể lo lắng về việc Systemd sẽ sinh ra hàng trăm tiến trình đồng thời và làm sập VPS của mình. May mắn thay, Systemd đã có cơ chế bảo vệ tích hợp.
Quy tắc mỗi lần một thực thể
Nếu .service của bạn đang chạy, Systemd sẽ không khởi chạy thực thể thứ hai. Nó sẽ đợi tác vụ hiện tại kết thúc. Nếu có các sự kiện mới xảy ra trong thời gian đó, Systemd sẽ đưa chúng vào hàng đợi và kích hoạt service thêm đúng một lần nữa. Cơ chế gom nhóm (batching) tự động này ngăn máy chủ của bạn bị quá tải bởi các thay đổi file liên tục.
Giám sát nhiều vị trí
Bạn có thể theo dõi nhiều file trong cùng một unit. Tôi thường sử dụng cách này để giám sát nhiều file cấu hình cùng lúc:
[Path]
PathModified=/etc/myapp/config.json
PathModified=/etc/myapp/users.db
Unit=reload-app.service
Bằng cách sử dụng chỉ thị Unit=, bạn có thể trỏ các file path khác nhau về cùng một service, giúp việc tự động hóa của bạn được tổ chức gọn gàng hơn.
Những bài học kinh nghiệm từ thực tế
Sau nhiều năm quản lý các unit này, tôi đã rút ra một vài chiến lược cụ thể để tránh những rắc rối thường gặp.
1. Gỡ lỗi với Journalctl
Nếu script không chạy, hãy kiểm tra nhật ký của cả path và service. Bạn có thể theo dõi quá trình chuyển giao theo thời gian thực bằng lệnh sau:
journalctl -u task-runner.path -u task-runner.service -f
2. Mô hình di chuyển nguyên tử (Atomic Move)
Khi di chuyển file vào một thư mục đang được giám sát, đừng bao giờ ghi trực tiếp vào thư mục đó. Thay vào đó, hãy ghi vào một vị trí tạm thời như /tmp và sử dụng lệnh mv để đưa nó vào thư mục đích. Vì mv là một thao tác nguyên tử (atomic operation) trong Linux, nó ngăn path unit kích hoạt trên một file mới ghi được một nửa hoặc bị hỏng.
3. Quyền hạn và quyền sở hữu
Systemd mặc định chạy dưới quyền root. Nếu script của bạn cần sửa đổi các file thuộc sở hữu của web server, hãy chỉ định user trong file .service. Điều này ngăn lỗi “Permission Denied” vốn thường khó phát hiện trong nhật ký.
[Service]
User=www-data
ExecStart=/var/www/scripts/process.sh
4. Phá vỡ vòng lặp vô tận
Hãy cẩn thận: nếu script của bạn sửa đổi chính file mà path unit đang theo dõi, bạn sẽ tạo ra một vòng lặp vô tận. Tôi đã từng vô tình tạo ra 10GB nhật ký chỉ trong một giờ vì một script cập nhật dấu thời gian trong chính file kích hoạt của nó. Luôn ghi kết quả hoặc nhật ký vào một thư mục khác để đảm bảo an toàn.
Tổng kết
Systemd Path unit là một giải pháp thay thế sạch sẽ và hiện đại hơn cho việc thăm dò bằng Cron truyền thống. Chúng phản ứng tức thì, tiết kiệm tài nguyên CPU và tích hợp hoàn hảo với hệ sinh thái Systemd. Cho dù bạn đang xây dựng một công cụ tự động sao lưu hay một hệ thống tiếp nhận dữ liệu phức tạp, các unit này là một bổ sung quan trọng cho bộ công cụ của bất kỳ quản trị viên hệ thống nào.

