Chuyển đến nội dung chính (Skip to content)
Mục lục bài viết
Linux

Tự động hóa tác vụ bằng cron và systemd timer

Tự động hóa tác vụ bằng cron và systemd timer

Lập lịch script trên Linux bằng cron hoặc systemd timer; thiết lập user, PATH, log và khóa chống chạy trùng, rồi kiểm tra exit code cùng dữ liệu đầu ra.

Script chạy thành công trong terminal nhưng không chạy đúng lúc 2 giờ sáng thường khác nhau ở user, PATH, thư mục hiện tại hoặc quyền truy cập. Scheduler không tự mang toàn bộ môi trường shell tương tác vào tác vụ. Bài này dùng Ubuntu Server 24.04 LTS để lập lịch một script backup lab bằng cron hoặc systemd timer và kiểm tra cả log lẫn đầu ra.

Chỉ lập lịch sau khi chạy thủ công thành công

Chuẩn bị dữ liệu fixture và thư mục copies từ bài rsync/tar trước. Tài khoản labadmin phải đọc được source và ghi được đích. Không dùng dữ liệu ứng dụng đang thay đổi hoặc database đang chạy cho script mẫu này.

Bạn cần xác định tác vụ chạy dưới user nào, khi nào, thời gian tối đa chấp nhận được, cách tránh chạy trùng và ai nhận thông báo khi thất bại. Chỉ tạo file log không đồng nghĩa đã có cảnh báo; nếu không có người hoặc hệ thống đọc, một tác vụ hỏng có thể âm thầm kéo dài.

Trong lab, chọn một trong hai scheduler để vận hành chính. Có thể thực hành cả hai nhưng phải tắt lịch thứ nhất trước khi bật lịch thứ hai, tránh chạy cùng một công việc hai lần. Kiểm tra timezone bằng timedatectl trước khi quy định lịch.

Tạo script dùng đường dẫn rõ ràng

Tạo /usr/local/bin/lab-backup do root sở hữu, không cho tài khoản dịch vụ tùy tiện sửa nội dung:

#!/bin/bash
set -euo pipefail
umask 0077
source_dir=/srv/backup-lab/source
backup_dir=/srv/backup-lab/copies
test -d "$source_dir"
test -d "$backup_dir"
exec 9>"$backup_dir/lab-backup.lock"
/usr/bin/flock -n 9 || exit 75
stamp=$(/usr/bin/date -u +%Y%m%dT%H%M%S%N)
archive="$backup_dir/source-$stamp.tar.gz"
/usr/bin/tar -czf "$archive" -C /srv/backup-lab source
/usr/bin/sha256sum "$archive" > "$archive.sha256"
printf 'backup_ok %s\n' "$archive"

Script ghi archive có tên theo thời điểm UTC, kèm checksum. Nó chưa có retention hay chuyển bản sao ra máy khác, nên chưa phải giải pháp backup production. Theo dõi dung lượng và chỉ bổ sung cơ chế xóa bản cũ sau khi xác định policy cụ thể.

Lock nằm trong thư mục do user chạy tác vụ ghi được. flock -n không chờ khi đã có lần chạy giữ lock; exit 75 ở ví dụ là quy ước của script cần được hệ giám sát hiểu. Không biến mọi lần không chạy vì lock thành “thành công” nếu điều đó có thể che một tiến trình mắc kẹt lâu dài.

set -euo pipefail giúp một số dạng lỗi làm script dừng, nhưng không thay thế xử lý trạng thái và thiết kế rollback. Nếu tar thất bại giữa chừng, archive một phần có thể còn lại. Chỉ coi mốc có đủ exit thành công, checksum và kiểm tra cần thiết là bản backup hoàn tất; không dùng tên file tồn tại như tiêu chí duy nhất.

Đặt executable và thử bằng đúng user:

sudo chmod 755 /usr/local/bin/lab-backup
sudo -u labadmin /usr/local/bin/lab-backup

Đọc đầu ra và kiểm tra archive. Thử restore một bản trước khi lập lịch. Nếu script cần credential, dùng cơ chế secret phù hợp với hệ thống; không viết token vào command line của cron hoặc log debug.

Lập lịch bằng crontab của người dùng

crontab -e

Ví dụ trong crontab của labadmin:

SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
15 2 * * * /usr/local/bin/lab-backup >> /srv/backup-lab/copies/cron-backup.log 2>&1

Lịch này chạy lúc 02:15 mỗi ngày theo cách triển khai cron và timezone được cấu hình. Đây là crontab người dùng nên không thêm cột username. File /etc/crontab và /etc/cron.d có định dạng khác, thường có thêm user; nhầm hai định dạng có thể khiến tác vụ không chạy.

Ký tự % trong phần command của cron có ý nghĩa đặc biệt theo implementation. Để tránh một lỗi phổ biến, script tự xử lý timestamp thay vì đưa date +%... trực tiếp vào dòng cron. Đối chiếu man 5 crontab trên Ubuntu đang dùng, vì tính năng timezone và phần mở rộng không giống nhau giữa mọi triển khai cron.

Kiểm tra crontab -l và systemctl status cron. Nếu dùng sudo crontab -e, bạn đang sửa crontab của root chứ không phải tài khoản thường. Không chạy tất cả tác vụ bằng root chỉ để bỏ qua lỗi quyền đích.

Mô hình các thành phần liên quan: Tự động hóa tác vụ bằng cron và systemd timer
Mô hình kỹ thuật để giải thích cơ chế; không phải bằng chứng kiểm thử.

Thử cron bằng lịch ngắn rồi trả về lịch thật

Trong lab, có thể tạm dùng * * * * * để chờ một lần chạy trong vài phút. Ghi thời điểm bắt đầu, kiểm tra file log và archive mới. Sau khi thấy kết quả, thay lại lịch dự định; không để tác vụ backup mỗi phút kéo dài vô hạn.

Cron thường không tự chạy bù mọi lịch đã bỏ lỡ trong lúc máy tắt. Cách xử lý phụ thuộc công cụ và cấu hình; nếu cần chạy bù, xem anacron hoặc timer phù hợp thay vì giả định cron đã làm. Những thay đổi giờ mùa hè ở timezone áp dụng DST cũng cần được xem xét với lịch theo giờ địa phương.

Nếu không có log, kiểm tra user, đường dẫn, quyền mở file chuyển hướng và daemon cron. Shell phải mở được file log trước khi script chạy; một lỗi quyền ở destination có thể khiến script chưa được thực thi. Log service của cron giúp biết scheduler đã gọi lệnh, còn log script mới cho biết công việc bên trong thành công hay không.

Tạo systemd service cho tác vụ một lần

Tắt dòng cron thử trước khi bật timer. Tạo /etc/systemd/system/lab-backup.service:

[Unit]
Description=Backup static Linux lab data

[Service]
Type=oneshot
User=labadmin
Group=labadmin
ExecStart=/usr/local/bin/lab-backup

Không đặt RemainAfterExit=yes trong mẫu này. Nếu service giữ trạng thái active sau khi hoàn thành, các lần timer tiếp theo có thể không kích hoạt lại theo ý định. Các thuộc tính sandbox bổ sung cần được thử với thư mục đọc/ghi thực tế, không chép một bộ hardening rồi bỏ qua lỗi backup.

Tạo /etc/systemd/system/lab-backup.timer:

[Unit]
Description=Daily Linux lab backup schedule

[Timer]
OnCalendar=*-*-* 02:15:00
Persistent=true

[Install]
WantedBy=timers.target

Persistent=true hỗ trợ kích hoạt bù lịch calendar đã bỏ lỡ theo cơ chế timer; không có nghĩa chạy lại từng lần bị lỡ hoặc đảm bảo đúng giây. AccuracySec, tải hệ thống và thời điểm máy hoạt động có thể ảnh hưởng lúc thực thi. Đối chiếu systemd.timer cho hành vi chính xác.

Kiểm tra timer và kết quả service

sudo systemd-analyze verify /etc/systemd/system/lab-backup.service /etc/systemd/system/lab-backup.timer
systemd-analyze calendar '*-*-* 02:15:00'
sudo systemctl daemon-reload
sudo systemctl start lab-backup.service
sudo systemctl enable --now lab-backup.timer
systemctl list-timers --all
sudo journalctl -u lab-backup.service --since '-15 minutes' --no-pager

Start service thủ công giúp kiểm tra môi trường systemd trước khi chờ timer. Trong lab có thể dùng lịch ngắn tạm thời để kiểm tra trigger, rồi phục hồi OnCalendar và reload định nghĩa. Chỉ thấy timer active chưa chứng minh backup tạo được archive hợp lệ.

Một service oneshot hoàn tất thường trở về inactive khi không giữ active; trạng thái đó chưa chắc là thất bại. Đọc Result, ExecMainStatus, journal và đầu ra. Timer mặc định cùng tên sẽ kích hoạt service tương ứng, nên tên file phải khớp hoặc khai báo Unit= rõ ràng.

Sơ đồ các bước kiểm tra: Tự động hóa tác vụ bằng cron và systemd timer
Sơ đồ chẩn đoán: kiểm tra theo từng lớp trước khi thay đổi cấu hình.

Kiểm tra lỗi, chạy trùng và phục hồi

Thử một lần với source lab không tồn tại, ghi nhận script trả lỗi và không xuất backup_ok, rồi phục hồi đường dẫn. Với lock, giữ lock trong một tiến trình lab và gọi script để xác nhận nó không tạo archive chồng. Không gây lỗi bằng cách đổi quyền thư mục production.

Kết thúc khi tác vụ chạy dưới đúng user, chỉ có một scheduler có hiệu lực, có log và exit code rõ, archive kiểm tra được và restore thành công vào nơi riêng. Tài liệu bàn giao cần ghi lịch cùng timezone, đường dẫn script, nơi log, chính sách dung lượng và người xử lý khi thất bại.

Đừng để log và archive tăng không giới hạn

Ví dụ cố ý chưa xóa bản cũ để người học không vô tình mất dữ liệu trong lần đầu thực hành. Khi đưa vào vận hành, phải chọn thời hạn giữ, dung lượng dự phòng và điều kiện xác nhận bản mới đủ tốt trước khi xóa bản cũ. Thiết kế retention theo mục tiêu phục hồi, không chỉ chọn một số ngày vì thấy có trong script trên mạng.

Log chuyển hướng bằng cron cũng có thể làm đầy filesystem. Chọn nơi lưu được bảo vệ, cơ chế rotation phù hợp và cách phát hiện log không còn ghi được. Nếu dùng journal, hiểu policy lưu và quyền đọc để người hỗ trợ lấy được bằng chứng khi tác vụ thất bại.

Bàn giao lịch như một thành phần vận hành

Ghi rõ vì sao chọn cron hoặc timer. Cron thuận tiện cho lịch đơn giản và quen thuộc; systemd timer có quan hệ unit cùng journal dễ theo dõi trên máy dùng systemd. Không cần chuyển mọi lịch cũ chỉ để đồng nhất nếu thay đổi chưa đem lại lợi ích và chưa được kiểm chứng.

Khi thay lịch, lưu cấu hình cũ, xác nhận lịch mới và kiểm tra không còn dòng trùng ở user khác, /etc/cron.d hoặc một timer đang bật. Nếu một công việc chạy hai lần, xem toàn bộ nguồn lập lịch thay vì chỉ sửa script. Sau đó theo dõi ít nhất một lần kích hoạt thật và kiểm tra bản backup mới có thể phục hồi.

Bài liên quan

Tìm hiểu thêm