Ένας server αξίζει τα λεφτά του όταν δουλεύει ενώ κοιμάστε: backups, εναλλαγή logs, ανανέωση πιστοποιητικών, μια αναφορά στις εννιά. Το Linux έχει δύο χρονοπρογραμματιστές γι' αυτό. Το cron είναι σαράντα χρονών και θέλει μία γραμμή. Οι timers του systemd θέλουν δύο μικρά αρχεία και δίνουν σε αντάλλαγμα logs, αναπλήρωση μετά από διακοπή και ακριβή ώρα. Αυτός ο οδηγός καλύπτει και τα δύο στο Ubuntu 24.04, με κάθε συμπεριφορά ελεγμένη σε νέο server από το image μας, μαζί με τα τρία λάθη που κάνουν μια εργασία cron να αποτυγχάνει χωρίς λέξη.
Χρειάζεστε χρήστη με sudo· ο οδηγός ρύθμισης Ubuntu δημιουργεί έναν.
1. Το cron σε πέντε λεπτά
Το cron είναι εγκατεστημένο και τρέχει στα images Ubuntu και Debian μας. Κάθε χρήστης έχει πίνακα εργασιών· επεξεργαστείτε τον δικό σας με:
crontab -e
Κάθε γραμμή έχει πέντε πεδία χρόνου και μια εντολή:
# min hour day month weekday command
30 3 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
*/5 * * * * /usr/local/bin/check.sh
0 9 * * 1-5 /usr/local/bin/report.sh
@reboot /usr/local/bin/start-tunnel.sh
Δηλαδή: στις 03:30 κάθε νύχτα, κάθε 5 λεπτά, στις 09:00 τις καθημερινές και μία φορά μετά από κάθε εκκίνηση. Το */5 σημαίνει κάθε πέμπτη τιμή, το 1-5 εύρος, το 1,15 λίστα. Ισχύει η ζώνη ώρας του server, UTC στα images μας· ορίστε τη δική σας μία φορά με τον οδηγό για hostname και ζώνη ώρας και το cron ακολουθεί.
Δείτε τι έτρεξε με journalctl -u cron. Κάθε εκτέλεση καταγράφει τον χρήστη και την εντολή, και εκεί φαίνονται οι τρεις παγίδες.
Παγίδα 1: η έξοδος εξαφανίζεται. Το cron στέλνει με email την έξοδο μιας εργασίας στον χρήστη. Το image μας δεν έχει mail server, οπότε το journal έγραφε (CRON) info (No MTA installed, discarding output) και η έξοδος χάθηκε. Ανακατευθύνετέ τη μόνοι σας, όπως το πρώτο παράδειγμα με >> /var/log/backup.log 2>&1.
Παγίδα 2: το σύμβολο του ποσοστού. Σε ένα crontab το % τερματίζει την εντολή και κάνει το υπόλοιπο τυπική είσοδο. Προγραμματίσαμε date +%F > /tmp/today. Το journal δείχνει τι έτρεξε πραγματικά το cron: CMD (date +). Δεν γράφτηκε αρχείο και κανένα σφάλμα δεν έφτασε σε εμάς. Γράψτε \% ή βάλτε την εντολή σε script και προγραμματίστε το script.
Παγίδα 3: διαφορετικό περιβάλλον. Το cron τρέχει τις εργασίες με /bin/sh, όχι bash, στον προσωπικό σας φάκελο και με λιτό περιβάλλον. Στο Ubuntu 24.04 το PATH ήταν καλύτερο από τη φήμη του: η πλήρης διαδρομή συστήματος μαζί με /usr/local/bin και /snap/bin, για root και για απλό χρήστη. Αυτό που λείπει ακόμη είναι ό,τι βρίσκεται στον προσωπικό σας φάκελο: ~/.local/bin, το node του nvm, pipx, cargo. Χρησιμοποιήστε πλήρεις διαδρομές στην εργασία ή ξεκινήστε τη γραμμή με . $HOME/.profile;.
Εργασίες που ανήκουν στο σύστημα και όχι σε χρήστη μπαίνουν στο /etc/cron.d/ ως αρχείο με ένα επιπλέον πεδίο, τον χρήστη:
30 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
Το Ubuntu τρέχει επίσης ό,τι υπάρχει στα /etc/cron.hourly, cron.daily, cron.weekly και cron.monthly, στο 17ο λεπτό κάθε ώρας, στις 06:25, στις 06:47 την Κυριακή και στις 06:52 την 1η του μήνα. Βάλτε εκεί ένα εκτελέσιμο script και θα τρέχει μαζί με τα υπόλοιπα.
2. Timers του systemd
Ένας timer είναι δύο units: μια υπηρεσία που κάνει τη δουλειά και ένας timer που λέει πότε. Δημιουργήστε πρώτα το script, μετά τα units.
sudo nano /usr/local/bin/backup.sh
sudo chmod +x /usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
sudo nano /etc/systemd/system/backup.timer
[Unit]
Description=Run the backup every night at 03:30
[Timer]
OnCalendar=*-*-* 03:30
Persistent=true
AccuracySec=1m
[Install]
WantedBy=timers.target
Ενεργοποιήστε τον timer, όχι την υπηρεσία:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer
Το list-timers δείχνει την επόμενη εκτέλεση, πόσος χρόνος μένει και την τελευταία εκτέλεση. Τα logs δεν θέλουν ρύθμιση: το journalctl -u backup.service έχει κάθε έναρξη, κάθε τέλος και κάθε γραμμή εξόδου με χρονοσφραγίδα. Για να τρέξετε την εργασία αμέσως, sudo systemctl start backup.service· έτσι δοκιμάζετε και το script πριν εμπιστευτείτε το πρόγραμμα.
Σύνταξη ημερολογίου. Το OnCalendar διαβάζεται ημέρα-εβδομάδας έτος-μήνας-ημέρα ώρα:λεπτό:δευτερόλεπτο, με * για οποιαδήποτε τιμή. Δοκιμάστε μια έκφραση πριν τη χρησιμοποιήσετε:
systemd-analyze calendar "Mon..Fri *-*-* 03:00" --iterations 2
Τυπώνει την κανονικοποιημένη μορφή και τις επόμενες ημερομηνίες. Μερικές εκφράσεις που ελέγξαμε:
| OnCalendar | Σημασία |
|---|---|
*-*-* 03:30 | Κάθε μέρα στις 03:30 |
Mon..Fri *-*-* 09:00 | Καθημερινές στις 09:00 |
*:0/15 | Κάθε 15 λεπτά |
weekly | Δευτέρα στις 00:00 |
*-*-01 04:00 | Την 1η κάθε μήνα στις 04:00 |
*-*-* 03:00 Europe/Kyiv | 03:00 ώρα Κιέβου· έτρεξε στις 01:00 UTC στη δοκιμή μας |
Οι τρεις ρυθμίσεις που αξίζει να ξέρετε. Το Persistent=true αποθηκεύει την τελευταία εκτέλεση στον δίσκο και αναπληρώνει μια εκτέλεση που χάθηκε όσο ο server ήταν κλειστός ή ο timer σταματημένος. Σταματήσαμε τον timer μας ανά δύο λεπτά, περιμέναμε να περάσει μια προγραμματισμένη εκτέλεση και τον ξεκινήσαμε ξανά: η χαμένη εκτέλεση ξεκίνησε μέσα στο ίδιο δευτερόλεπτο. Χωρίς Persistent, απλώς περιμένει την επόμενη ευκαιρία.
Το AccuracySec είναι η έκπληξη. Από προεπιλογή το systemd ομαδοποιεί τους timers σε παράθυρο ενός λεπτού για να γλιτώνει αφυπνίσεις, γι' αυτό η πρώτη μας εκτέλεση ήρθε στις 07:42:18 και όχι στις 07:42:00. Με AccuracySec=1s οι επόμενες έπεσαν ακριβώς στο δευτερόλεπτο, 07:46:00 και 07:48:00. Ορίστε το όταν μετράει το λεπτό· αφήστε την προεπιλογή για ένα νυχτερινό backup.
Το RandomizedDelaySec=10m κάνει σκόπιμα το αντίθετο: απλώνει την εκκίνηση σε ένα παράθυρο ώστε δέκα servers να μη χτυπήσουν τον ίδιο χώρο backup το ίδιο δευτερόλεπτο.
Για μια εργασία μίας φοράς, κανένα αρχείο:
sudo systemd-run --on-active=30m --unit=cleanup-once /usr/local/bin/cleanup.sh
Δημιουργεί έναν προσωρινό timer που ενεργοποιείται μία φορά και εξαφανίζεται· μέχρι τότε τον δείχνει το systemctl list-timers.
3. Ποιο να χρησιμοποιήσετε
| Cron | Timer του systemd | |
|---|---|---|
| Ρύθμιση | 1 γραμμή | 2 αρχεία |
| Logs | Μόνο αν ανακατευθύνετε την έξοδο | journalctl -u name.service |
| Χαμένη εκτέλεση όσο ο server ήταν κλειστός | Χάνεται | Τρέχει στην εκκίνηση με Persistent=true |
| Η εργασία τρέχει ακόμη στο επόμενο χτύπημα | Ξεκινά δεύτερο αντίγραφο | Παραλείπεται μέχρι να τελειώσει το πρώτο |
| Ακριβής ώρα | Στο λεπτό | Στο δευτερόλεπτο με AccuracySec=1s |
| Κατάσταση | Καμία | list-timers, systemctl status |
Χρησιμοποιήστε cron για μια γρήγορη γραμμή που θα αναγνωρίζετε και σε έναν χρόνο. Χρησιμοποιήστε timer για ό,τι πρέπει να βλέπετε όταν αποτυγχάνει, δεν πρέπει να επικαλύπτεται ή πρέπει να τρέξει μετά από χαμένη επανεκκίνηση: backups, ανανέωση πιστοποιητικών, καθαρισμός βάσεων δεδομένων. Αν μια εργασία cron μπορεί να επικαλυφθεί, τυλίξτε τη: flock -n /tmp/backup.lock /usr/local/bin/backup.sh, και το δεύτερο αντίγραφο τερματίζει αμέσως.
Και οι δύο χρονοπρογραμματιστές ξεκινούν μια εργασία και σταματούν. Για πρόγραμμα που πρέπει να τρέχει όλο το εικοσιτετράωρο και να επανέρχεται μετά από κατάρρευση, χρειάζεστε υπηρεσία, όχι πρόγραμμα· δείτε πώς δημιουργείτε υπηρεσία systemd και, για Windows, πώς τρέχετε script 24/7 σε Windows Server. Ένας καλός πρώτος timer είναι αυτός από τον οδηγό μας για backup με restic· οι αυτόματες ενημερώσεις ασφαλείας είναι ένας timer που το Ubuntu ήδη έχει, το apt-daily-upgrade.timer, ένας από τους 17 που τρέχουν σε νέο server.
Σχόλια
Δεν υπάρχουν ακόμη σχόλια. Γίνετε ο πρώτος.