งานประจำของผู้ดูแลระบบมักเต็มไปด้วยคำสั่งที่ต้องทำซ้ำ เช่น สำรองข้อมูลทุกคืน ลบ Log เก่า ตรวจสอบพื้นที่ Disk หรือเรียก Script เพื่อส่งรายงานสถานะ Server
เครื่องมือที่ผู้ใช้ Linux คุ้นเคยที่สุดคือ Cron เพราะตั้งค่าง่ายและใช้กันมานาน แต่บน Linux รุ่นใหม่ที่ใช้ systemd เรามีอีกทางเลือกคือ systemd Timer ซึ่งทำงานร่วมกับ Service, Journal, Dependency และระบบ Security ของ systemd ได้โดยตรง
คำถามสำคัญจึงไม่ใช่เพียงว่า “ตัวไหนดีกว่า” แต่คือ งานประเภทใดควรใช้ Cron และงานประเภทใดควรใช้ systemd Timer
บทความนี้จะเปรียบเทียบทั้งสองระบบ พร้อมทดลองตั้งเวลา Backup ไดเรกทอรี /etc บน Ubuntu Server 26.04 LTS ด้วยวิธีที่นำไปใช้งานจริงได้ทันที
สภาพแวดล้อมที่ใช้ในบทความ
บทความนี้อ้างอิงจากระบบต่อไปนี้
-
OS: Ubuntu Server 26.04 LTS
-
systemd: 259.5
-
cron: 3.0pl1-200ubuntu1
-
Shell: Bash
-
สิทธิ์ผู้ใช้งาน: ผู้ใช้ทั่วไปที่สามารถใช้
sudo
Ubuntu 26.04 LTS มีแพ็กเกจ systemd รุ่น 259.5 และแพ็กเกจ cron รุ่น 3.0pl1-200ubuntu1 อยู่ใน Repository อย่างเป็นทางการ ณ วันที่จัดทำบทความ
ตรวจสอบเวอร์ชันของระบบด้วยคำสั่ง
# ตรวจสอบเวอร์ชัน Ubuntu
lsb_release -a
# ตรวจสอบเวอร์ชัน systemd
systemctl --version
# ตรวจสอบแพ็กเกจ cron
apt policy cron

Cron คืออะไร
Cron คือระบบตั้งเวลาสำหรับเรียก Command หรือ Script ตามวันและเวลาที่กำหนด โดย Cron daemon จะอ่านตารางเวลาที่เรียกว่า crontab
ผู้ใช้แต่ละคนสามารถมี crontab ของตัวเองได้ และคำสั่งใน crontab จะทำงานด้วยสิทธิ์ของผู้ใช้เจ้าของ crontab นั้น
รูปแบบพื้นฐานของ Cron มี 5 ช่องเวลา ตามด้วยคำสั่ง
นาที ชั่วโมง วันที่ เดือน วันในสัปดาห์ คำสั่ง
ตัวอย่าง
30 2 * * * /usr/local/sbin/backup-etc.sh
หมายถึงเรียก Script ทุกวันเวลา 02:30 น.
ตารางค่าที่ใช้งานได้มีดังนี้
| ตำแหน่ง | ความหมาย | ค่าที่กำหนดได้ |
|---|---|---|
| 1 | นาที | 0–59 |
| 2 | ชั่วโมง | 0–23 |
| 3 | วันที่ของเดือน | 1–31 |
| 4 | เดือน | 1–12 |
| 5 | วันในสัปดาห์ | 0–7 โดย 0 และ 7 คือวันอาทิตย์ |
Cron รองรับเครื่องหมาย * สำหรับทุกค่า เครื่องหมาย , สำหรับระบุหลายค่า เครื่องหมาย - สำหรับช่วง และ / สำหรับกำหนด Step เช่น */5 หมายถึงทุก 5 หน่วย
ข้อควรระวังคือ หากกำหนดทั้งวันที่ของเดือนและวันในสัปดาห์ Cron จะเรียกงานเมื่อ ช่องใดช่องหนึ่งตรงเงื่อนไข ไม่ได้รอให้ทั้งสองช่องตรงพร้อมกัน
systemd Timer คืออะไร
systemd Timer คือ Unit ประเภทหนึ่งของ systemd ใช้สำหรับกำหนดเวลาที่จะเรียก Service อีก Unit หนึ่ง
โดยทั่วไปจะประกอบด้วยไฟล์สองไฟล์
ชื่อบริการ.service
ชื่อบริการ.timer
ไฟล์ .service กำหนดว่าให้ทำงานอะไร ส่วนไฟล์ .timer กำหนดว่าให้ทำงานเมื่อใด
systemd Timer รองรับทั้งเวลาตามปฏิทินผ่าน OnCalendar= และเวลาที่อ้างอิงจากเหตุการณ์ เช่น หลัง Boot หรือหลัง Service ทำงานครั้งล่าสุด
ตัวอย่างรูปแบบเวลา
OnCalendar=*-*-* 02:30:00
หมายถึงทำงานทุกวันเวลา 02:30 น.
systemd รองรับ Calendar Expression ที่ยืดหยุ่นกว่า Cron เช่น
# ทุกวันจันทร์ถึงศุกร์ เวลา 08:30
OnCalendar=Mon..Fri *-*-* 08:30:00
# วันที่ 1 ของทุกเดือน เวลาเที่ยงคืน
OnCalendar=*-*-01 00:00:00
# ทุก ๆ ชั่วโมง
OnCalendar=hourly
# ทุกวัน
OnCalendar=daily
สามารถใช้คำสั่ง systemd-analyze calendar เพื่อตรวจสอบ Expression และดูเวลาที่จะทำงานครั้งต่อไปได้
เปรียบเทียบ Cron กับ systemd Timer
| คุณสมบัติ | Cron | systemd Timer |
|---|---|---|
| ความง่ายในการตั้งค่า | ง่ายมาก ใช้เพียงบรรทัดเดียว | ต้องสร้าง .service และ .timer |
| ความคุ้นเคย | ใช้งานแพร่หลายมานาน | เหมาะกับ Linux ที่ใช้ systemd |
| การดู Log | ต้อง Redirect หรือดู Log ของ cron | ดูผ่าน journalctl ได้โดยตรง |
| งานที่พลาดตอนปิดเครื่อง | ปกติจะไม่ย้อนกลับมาทำ | ใช้ Persistent=true ได้ |
| Dependency | ต้องเขียนตรวจสอบเอง | ใช้ After=, Wants= และ Requires= |
| จำกัดสิทธิ์และ Resource | ต้องใช้เครื่องมือเพิ่มเติม | รองรับ Security และ Resource Control |
| ป้องกันงานซ้อน | ต้องใช้ flock หรือเขียน Lock เอง |
systemd ติดตามสถานะ Service ให้ |
| ทดสอบตารางเวลา | ต้องวิเคราะห์ Cron Expression | ใช้ systemd-analyze calendar |
| Portability | ใช้ได้กับ Unix/Linux หลายระบบ | ใช้ได้บนระบบที่ใช้ systemd |
| เหมาะกับ | งานง่ายและ Script ขนาดเล็ก | งานระดับระบบและ Production |
เตรียม Script สำหรับทดสอบ
เราจะสร้าง Script สำหรับสำรองข้อมูล /etc ไปยัง /var/backups/syswriter และลบ Backup ที่เก่ากว่า 7 วัน
⚠️ ข้อควรระวัง: ตัวอย่างนี้อ่านข้อมูลจาก /etc และเขียนไฟล์ลง /var/backups จึงต้องใช้สิทธิ์ระดับ Administrator ควรตรวจสอบพื้นที่ Disk ก่อนนำไปใช้กับ Server จริง
สร้างไดเรกทอรีสำหรับเก็บ Backup
# สร้างไดเรกทอรีและอนุญาตให้ root เข้าถึงเท่านั้น
sudo install -d -m 0700 /var/backups/syswriter
สร้าง Script
sudo nano /usr/local/sbin/backup-etc.sh
เพิ่มเนื้อหาต่อไปนี้
#!/usr/bin/env bash
# หยุดทันทีเมื่อเกิดข้อผิดพลาด ตัวแปรไม่มีค่า หรือ Pipeline ล้มเหลว
set -Eeuo pipefail
# ไฟล์ Backup ที่สร้างใหม่จะไม่เปิดสิทธิ์ให้ผู้ใช้อื่นอ่าน
umask 077
BACKUP_DIR="/var/backups/syswriter"
TIMESTAMP="$(/usr/bin/date +'%Y%m%d-%H%M%S')"
ARCHIVE="${BACKUP_DIR}/etc-${TIMESTAMP}.tar.gz"
# ตรวจสอบและสร้างไดเรกทอรี Backup
/usr/bin/install -d -m 0700 "${BACKUP_DIR}"
# สำรองข้อมูลไดเรกทอรี /etc
/usr/bin/tar \
--one-file-system \
--create \
--gzip \
--file="${ARCHIVE}" \
/etc
# ลบไฟล์ Backup ที่เก่ากว่า 7 วัน
/usr/bin/find "${BACKUP_DIR}" \
-type f \
-name 'etc-*.tar.gz' \
-mtime +7 \
-delete
echo "Backup completed: ${ARCHIVE}"
กำหนด Permission
# เจ้าของไฟล์อ่าน เขียน และรันได้ ส่วนผู้ใช้อื่นไม่มีสิทธิ์
sudo chmod 0700 /usr/local/sbin/backup-etc.sh
sudo chown root:root /usr/local/sbin/backup-etc.sh
ทดลองเรียก Script ด้วยตนเอง
sudo /usr/local/sbin/backup-etc.sh
ตรวจสอบไฟล์ที่สร้างขึ้น
sudo ls -lh /var/backups/syswriter/
ตรวจสอบว่าไฟล์ Archive เปิดอ่านได้
# แสดง 20 รายการแรกภายในไฟล์ Backup
sudo tar -tzf /var/backups/syswriter/etc-*.tar.gz | head -n 20
ภาพหน้าจอที่แนะนำ: ไฟล์ Backup ภายใน /var/backups/syswriter
วิธีที่ 1 ตั้งเวลาด้วย Cron
ติดตั้งและตรวจสอบ Cron
ตรวจสอบสถานะ Cron
sudo systemctl status cron --no-pager
หากยังไม่มีแพ็กเกจ Cron ให้ติดตั้งด้วยคำสั่ง
sudo apt update
sudo apt install -y cron
เปิดใช้งาน Service
sudo systemctl enable --now cron
เพิ่ม Cron Job
เนื่องจาก Script ต้องอ่านไฟล์ระบบใน /etc เราจะเพิ่มงานลงใน crontab ของ root ผ่าน sudo โดยไม่ Login เป็น root โดยตรง
sudo crontab -e
เพิ่มบรรทัดต่อไปนี้
# สำรองข้อมูลทุกวันเวลา 02:30 น.
# ใช้ flock ป้องกันไม่ให้มีงานมากกว่าหนึ่งชุดทำงานพร้อมกัน
30 2 * * * /usr/bin/flock -n /run/syswriter-backup.lock /usr/local/sbin/backup-etc.sh >> /var/log/syswriter-backup.log 2>&1
ส่วนประกอบของคำสั่งมีดังนี้
-
30 2 * * *เรียกงานทุกวันเวลา 02:30 น. -
/usr/bin/flock -nป้องกันการทำงานซ้อนกัน -
/run/syswriter-backup.lockเป็น Lock file -
>>เพิ่มผลลัพธ์ต่อท้ายไฟล์ Log -
2>&1ส่ง Error ไปเก็บรวมกับ Standard Output
ตรวจสอบรายการ Cron Job
sudo crontab -l
ตรวจสอบ Log ของ Script
sudo tail -n 50 /var/log/syswriter-backup.log
ตรวจสอบ Log ของ Cron daemon
sudo journalctl -u cron --since today
ภาพหน้าจอที่แนะนำ: ผลลัพธ์ sudo crontab -l และ journalctl -u cron
ข้อผิดพลาดที่พบบ่อยเมื่อใช้ Cron
Cron หา Command ไม่พบ
Cron มี Environment และค่า PATH ที่จำกัดกว่าตอนใช้งานผ่าน Terminal จึงควรใช้ Absolute path เช่น
/usr/bin/tar
/usr/bin/date
/usr/bin/find
แทนการเขียนเพียง
tar
date
find
Script ทำงานเองได้ แต่ Cron ไม่ทำงาน
ตรวจสอบ Permission ของ Script
sudo ls -l /usr/local/sbin/backup-etc.sh
ตรวจสอบ Shebang บรรทัดแรก
#!/usr/bin/env bash
และตรวจสอบว่าไฟล์ใช้ Line Ending แบบ Linux ไม่ใช่ Windows CRLF
file /usr/local/sbin/backup-etc.sh
งานทำงานซ้อนกัน
Cron ไม่ทราบโดยตรงว่างานครั้งก่อนยังทำงานอยู่หรือไม่ จึงควรใช้ flock กับงาน Backup, Sync หรือ Import ข้อมูลที่อาจใช้เวลานาน
วิธีที่ 2 ตั้งเวลาด้วย systemd Timer
systemd Timer จะแยกส่วนการทำงานออกจากส่วนกำหนดเวลาอย่างชัดเจน
สร้าง Service Unit
สร้างไฟล์ Service
sudo nano /etc/systemd/system/syswriter-backup.service
เพิ่มเนื้อหาต่อไปนี้
[Unit]
Description=Backup the /etc directory
Documentation=man:systemd.service(5)
[Service]
# เหมาะสำหรับงานที่ทำครั้งเดียวแล้วจบ
Type=oneshot
# ต้องใช้ root เพื่ออ่านไฟล์ระบบบางส่วนใน /etc
User=root
Group=root
# เรียก Script โดยใช้ Absolute path
ExecStart=/usr/local/sbin/backup-etc.sh
# จำกัดเวลาทำงานสูงสุด ป้องกัน Process ค้าง
RuntimeMaxSec=30min
# ไฟล์ที่สร้างใหม่ให้เฉพาะ root อ่านได้
UMask=0077
# ลดสิทธิ์และจำกัดพื้นที่ที่ Service เขียนข้อมูลได้
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/backups/syswriter
Type=oneshot เหมาะสำหรับงานที่เรียก Command ทำงานให้เสร็จแล้วหยุด เช่น Backup, Cleanup หรือ Generate Report โดย systemd จะรอจน Process จบก่อนพิจารณาว่า Service ทำงานสำเร็จหรือไม่
สร้าง Timer Unit
สร้างไฟล์ Timer
sudo nano /etc/systemd/system/syswriter-backup.timer
เพิ่มเนื้อหาต่อไปนี้
[Unit]
Description=Run /etc backup every day
[Timer]
# เรียกทุกวันเวลา 02:30 น.
OnCalendar=*-*-* 02:30:00
# หากเครื่องปิดอยู่ในเวลาที่กำหนด ให้ทำงานหลังเปิดเครื่อง
Persistent=true
# สุ่มหน่วงเวลาไม่เกิน 10 นาที ลดการทำงานพร้อมกันหลายเครื่อง
RandomizedDelaySec=10min
# อนุญาตให้ systemd รวมเวลาการทำงานภายในช่วง 1 นาที
AccuracySec=1min
# ระบุ Service ที่ Timer ต้องเรียก
Unit=syswriter-backup.service
[Install]
WantedBy=timers.target
Persistent=true ช่วยให้ Timer ตรวจสอบว่ามีรอบการทำงานที่พลาดไประหว่างเครื่องปิดหรือ Timer ไม่ได้ทำงานหรือไม่ หากพบว่าพลาดอย่างน้อยหนึ่งรอบ Service จะถูกเรียกหลัง Timer กลับมาทำงานอีกครั้ง
RandomizedDelaySec= เหมาะกับกรณีที่มี Server หลายเครื่อง เพราะช่วยลดปัญหาทุกเครื่องเริ่ม Backup หรือเชื่อมต่อ Storage พร้อมกัน
ตรวจสอบ Calendar Expression
ก่อนเปิดใช้งานควรตรวจสอบว่า Expression ถูกต้อง
systemd-analyze calendar '*-*-* 02:30:00'
ดูเวลาทำงาน 5 รอบถัดไป
systemd-analyze calendar \
--iterations=5 \
'*-*-* 02:30:00'
ตรวจสอบความถูกต้องของ Unit
sudo systemd-analyze verify \
/etc/systemd/system/syswriter-backup.service \
/etc/systemd/system/syswriter-backup.timer
หากไม่มีข้อความ Error แสดงว่า Syntax ถูกต้อง
เปิดใช้งาน Timer
แจ้งให้ systemd โหลด Unit ใหม่
sudo systemctl daemon-reload
เปิดใช้งาน Timer และให้เริ่มทำงานทันที
sudo systemctl enable --now syswriter-backup.timer
ตรวจสอบสถานะ
sudo systemctl status syswriter-backup.timer --no-pager
ดู Timer ทั้งหมด
systemctl list-timers --all
ผลลัพธ์จะแสดงข้อมูลสำคัญ เช่น
-
NEXTเวลาที่จะทำงานครั้งถัดไป -
LEFTเวลาที่เหลือ -
LASTเวลาที่ทำงานครั้งล่าสุด -
UNITชื่อ Timer -
ACTIVATESชื่อ Service ที่จะถูกเรียก
ภาพหน้าจอที่แนะนำ: ผลลัพธ์ systemctl list-timers --all
ทดสอบ systemd Service โดยไม่ต้องรอเวลา
เราสามารถสั่งเรียก Service โดยตรงเพื่อทดสอบได้
sudo systemctl start syswriter-backup.service
ตรวจสอบสถานะล่าสุด
sudo systemctl status syswriter-backup.service --no-pager
ดู Log ของ Service
sudo journalctl \
-u syswriter-backup.service \
--since today \
--no-pager
ติดตาม Log แบบ Real-time
sudo journalctl -fu syswriter-backup.service
ตรวจสอบไฟล์ Backup
sudo ls -lh /var/backups/syswriter/
ข้อดีของวิธีนี้คือไม่ต้องเขียน Redirect ไปยังไฟล์ Log เอง เพราะ Standard Output และ Standard Error จะถูกเก็บใน systemd Journal โดยอัตโนมัติ
การหยุดและลบ Timer
หยุดและปิดการเริ่มอัตโนมัติ
sudo systemctl disable --now syswriter-backup.timer
ลบไฟล์ Unit
sudo rm \
/etc/systemd/system/syswriter-backup.service \
/etc/systemd/system/syswriter-backup.timer
โหลด Configuration ใหม่
sudo systemctl daemon-reload
sudo systemctl reset-failed
⚠️ อย่าเปิดใช้งานทั้ง Cron Job และ systemd Timer สำหรับ Script เดียวกันพร้อมกัน เพราะจะทำให้ Backup ถูกเรียกซ้ำสองครั้งในช่วงเวลาเดียวกัน แม้จะมี flock ช่วยป้องกันบางกรณีก็ตาม
ควรเลือก Cron เมื่อใด
Cron เหมาะกับงานต่อไปนี้
-
งานมีเพียง Command หรือ Script สั้น ๆ
-
ไม่ต้องกำหนด Dependency กับ Service อื่น
-
ต้องการ Configuration ที่อ่านและแก้ไขได้รวดเร็ว
-
ต้องนำ Script ไปใช้กับ Unix หรือ Linux หลายตระกูล
-
เป็นงานระดับผู้ใช้ทั่วไป
-
ไม่ต้องการ Security Isolation หรือ Resource Control ขั้นสูง
ตัวอย่างงานที่เหมาะกับ Cron
# ลบไฟล์ชั่วคราวของผู้ใช้ทุกคืน
0 1 * * * /usr/bin/find /home/user/tmp -type f -mtime +7 -delete
ควรเลือก systemd Timer เมื่อใด
systemd Timer เหมาะกับงานต่อไปนี้
-
งานระดับระบบหรือ Production
-
ต้องการดู Log ด้วย
journalctl -
ต้องทำงานหลัง Network, Database หรือ Storage พร้อม
-
ต้องการทำงานชดเชยเมื่อ Server ถูกปิดในเวลาที่กำหนด
-
ต้องการจำกัด Runtime, CPU, Memory หรือสิทธิ์เข้าถึงระบบ
-
ต้องการตรวจสอบสถานะด้วย Monitoring
-
ต้องดู Exit status และจัดการ Failure อย่างเป็นระบบ
-
ต้องการกระจายเวลาทำงานของ Server หลายเครื่อง
ตัวอย่างเช่น งาน Backup ไปยัง NAS อาจเพิ่ม Dependency ได้ดังนี้
[Unit]
Description=Backup data to remote storage
# รอให้ระบบ Network พร้อมก่อนเริ่มงาน
Wants=network-online.target
After=network-online.target
อย่างไรก็ตาม network-online.target หมายถึงระบบ Network ผ่านขั้นตอนเตรียมพร้อมตามที่ Network manager รายงาน ไม่ได้ยืนยันว่า Internet หรือ Remote Server ปลายทางจะตอบสนองเสมอ ดังนั้น Script ควรตรวจสอบการเชื่อมต่อและจัดการ Error เพิ่มเติมด้วย
แนวทางเลือกใช้สำหรับ SysAdmin
หากเป็นงานง่ายและต้องการตั้งค่าให้เสร็จภายในไม่กี่นาที Cron ยังคงเป็นเครื่องมือที่เหมาะสมและไม่มีความจำเป็นต้องเปลี่ยนทุกงานไปเป็น systemd Timer
แต่หากงานนั้นสำคัญต่อระบบ เช่น Backup, Database Maintenance, Certificate Renewal, Log Processing หรือการส่งข้อมูลไปยังระบบภายนอก การใช้ systemd Timer จะช่วยให้ตรวจสอบสถานะ ดู Log กำหนด Dependency และควบคุม Security ได้ชัดเจนกว่า
แนวทางที่แนะนำคือ
งานส่วนตัวหรืองานขนาดเล็ก → Cron
งานระบบที่ต้องดูแลระยะยาว → systemd Timer
งานที่ต้องรองรับหลาย Unix → Cron
งานที่ต้องการ Log และ Dependency → systemd Timer
สรุป
Cron และ systemd Timer มีเป้าหมายเดียวกัน คือเรียก Command หรือ Script ตามเวลาที่กำหนด แต่มีแนวทางการออกแบบต่างกัน
Cron เด่นเรื่องความเรียบง่าย ใช้เพียงหนึ่งบรรทัดและเหมาะกับงานทั่วไป ส่วน systemd Timer ต้องสร้างไฟล์มากกว่า แต่ให้ความสามารถด้าน Logging, Dependency, Failure Tracking, Security และการทำงานชดเชยหลังเครื่องเปิดกลับมา
สำหรับ Ubuntu Server 26.04 งานง่ายสามารถใช้ Cron ต่อไปได้โดยไม่มีปัญหา แต่สำหรับงาน Production ที่ต้องตรวจสอบและดูแลระยะยาว systemd Timer มักเป็นตัวเลือกที่เหมาะสมกว่า
—
Write by Dr.Arnut Ruttanatirakul
(c) SysAdmin Knowledge
https://www.sysadmin.in.th
August 6, 2026

