EQVPS
DashboardKom i gang

Sådan planlægger du opgaver på en VPS med cron og systemd-timere

Kør backups, oprydning og scripts efter en tidsplan. Cron på fem minutter med de tre fælder, der stille ødelægger job, og derefter systemd-timere til logs, indhentning efter nedetid og præcis tid. Hver adfærd nedenfor er testet på en ny Ubuntu 24.04-server.

En server tjener sig selv ind ved at arbejde, mens du sover: backups, logrotation, fornyelse af certifikater, en rapport klokken ni. Linux har to planlæggere til det. Cron er fyrre år gammel og fylder én linje. Systemd-timere fylder to små filer og giver til gengæld logs, indhentning efter nedetid og præcis tid. Denne guide dækker begge på Ubuntu 24.04, med hver adfærd tjekket på en ny server fra vores image, inklusive de tre fejl, der får et cron-job til at fejle uden et ord.

Du skal bruge en bruger med sudo; guiden til opsætning af Ubuntu opretter en.

1. Cron på fem minutter

Cron er installeret og kører på vores Ubuntu- og Debian-images. Hver bruger har en jobtabel; rediger din med:

crontab -e

Hver linje består af fem tidsfelter og en kommando:

# 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

Det vil sige: 03:30 hver nat, hvert 5. minut, 09:00 på hverdage og én gang efter hver opstart. */5 betyder hver femte værdi, 1-5 et interval, 1,15 en liste. Serverens tidszone gælder, UTC på vores images; sæt din én gang med guiden om værtsnavn og tidszone, så følger cron.

Se, hvad der har kørt, med journalctl -u cron. Hver kørsel logger brugeren og kommandoen, og det er der, de tre fælder viser sig.

Fælde 1: outputtet forsvinder. Cron mailer et jobs output til brugeren. Vores image har ingen mailserver, så journalen viste (CRON) info (No MTA installed, discarding output), og outputtet var væk. Omdiriger det selv, som det første eksempel gør med >> /var/log/backup.log 2>&1.

Fælde 2: procenttegnet. I en crontab afslutter % kommandoen og gør resten til standardinput. Vi planlagde date +%F > /tmp/today. Journalen viser, hvad cron faktisk kørte: CMD (date +). Ingen fil blev skrevet, og ingen fejl nåede os. Skriv \%, eller læg kommandoen i et script og planlæg scriptet.

Fælde 3: et andet miljø. Cron kører job med /bin/sh, ikke bash, i din hjemmemappe og med et sparsomt miljø. På Ubuntu 24.04 var PATH bedre end sit ry: den fulde systemsti inklusive /usr/local/bin og /snap/bin, for root og for en almindelig bruger. Det, der stadig mangler, er alt under din hjemmemappe: ~/.local/bin, nvm's node, pipx, cargo. Brug fulde stier i jobbet, eller start linjen med . $HOME/.profile;.

Job, der hører til systemet frem for en bruger, lægges i /etc/cron.d/ som en fil med ét ekstra felt, brugeren:

30 3 * * * root /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

Ubuntu kører også alt i /etc/cron.hourly, cron.daily, cron.weekly og cron.monthly, 17 minutter over hver time, 06:25, 06:47 om søndagen og 06:52 den 1. Læg et kørbart script der, så kører det sammen med resten.

2. Systemd-timere

En timer er to units: en service, der udfører arbejdet, og en timer, der siger hvornår. Opret først scriptet, derefter 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

Aktivér timeren, ikke servicen:

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers backup.timer

list-timers viser næste kørsel, hvor lang tid der er til, og seneste kørsel. Logs kræver ingen opsætning: journalctl -u backup.service har hver start, hver afslutning og hver linje output med tidsstempel. For at køre jobbet med det samme, sudo systemctl start backup.service; det er også sådan, du tester scriptet, før du stoler på tidsplanen.

Kalendersyntaks. OnCalendar læses som ugedag år-måned-dag time:minut:sekund, med * for enhver værdi. Test et udtryk, før du bruger det:

systemd-analyze calendar "Mon..Fri *-*-* 03:00" --iterations 2

Det udskriver den normaliserede form og de næste datoer. Nogle udtryk, vi tjekkede:

OnCalendarBetydning
*-*-* 03:30Hver dag 03:30
Mon..Fri *-*-* 09:00Hverdage 09:00
*:0/15Hvert 15. minut
weeklyMandage 00:00
*-*-01 04:00Den 1. i hver måned 04:00
*-*-* 03:00 Europe/Kyiv03:00 Kyiv-tid; kørte 01:00 UTC hos os

De tre indstillinger, der er værd at kende. Persistent=true gemmer seneste kørsel på disken og indhenter en kørsel, der blev misset, mens serveren var slukket eller timeren stoppet. Vi stoppede vores timer hvert andet minut, ventede, til en planlagt kørsel var gået, og startede den igen: den missede kørsel gik i gang inden for samme sekund. Uden Persistent venter den bare på næste tidspunkt.

AccuracySec er overraskelsen. Systemd samler som standard timere inden for et vindue på et minut for at spare opvågninger, så vores første kørsel kom 07:42:18, ikke 07:42:00. Med AccuracySec=1s landede de næste kørsler på sekundet 07:46:00 og 07:48:00. Sæt den, når minuttet betyder noget; behold standarden til en natlig backup.

RandomizedDelaySec=10m gør med vilje det modsatte: den spreder starten over et vindue, så ti servere ikke rammer det samme backuplager i samme sekund.

Til et engangsjob skal der slet ingen filer til:

sudo systemd-run --on-active=30m --unit=cleanup-once /usr/local/bin/cleanup.sh

Det opretter en midlertidig timer, der går af én gang og forsvinder; indtil da viser systemctl list-timers den.

3. Hvilken skal du vælge

CronSystemd-timer
Opsætning1 linje2 filer
LogsKun hvis du omdirigerer outputjournalctl -u name.service
Misset kørsel, mens serveren var slukketTabtKører ved opstart med Persistent=true
Jobbet kører stadig ved næste tikEn anden kopi starterSpringes over, til den første er færdig
Præcis tidPå minuttetPå sekundet med AccuracySec=1s
StatusIngenlist-timers, systemctl status

Brug cron til en hurtig linje, du stadig genkender om et år. Brug en timer til alt, hvis fejl du skal kunne se, som ikke må overlappe, eller som skal køre efter en misset genstart: backups, fornyelse af certifikater, oprydning i databaser. Kan et cron-job overlappe, så pak det ind: flock -n /tmp/backup.lock /usr/local/bin/backup.sh, og den anden kopi afslutter med det samme.

Begge planlæggere starter et job og stopper så. Til et program, der skal køre døgnet rundt og komme tilbage efter et nedbrud, skal du bruge en service, ikke en tidsplan; se hvordan du opretter en systemd-service og til Windows hvordan du kører et script 24/7 på Windows Server. En god første timer er den fra vores guide til backup med restic; automatiske sikkerhedsopdateringer er en timer, Ubuntu allerede leverer, apt-daily-upgrade.timer, en af de 17, der kører på en ny server.

FAQ

Hvorfor virker mit job i terminalen, men ikke i cron?

Tre almindelige grunde. Cron kører jobbet med sh, ikke bash, så bash-syntaks fejler. Værktøjer i din hjemmemappe, som nvm, pipx eller cargo, er ikke i crons PATH, så brug fulde stier. Og ethvert % i kommandolinjen afslutter kommandoen: date +%F blev til date + på vores server. Skriv det som \% eller flyt kommandoen ind i et script.

Hvor bliver output fra cron af?

Det sendes som standard med e-mail. Vores image har ingen mailserver, så cron logger 'No MTA installed, discarding output', og outputtet er væk. Tilføj >> /var/log/myjob.log 2>&1 til jobbet, eller skift til en systemd-timer, hvis output selv lander i journalen.

Hvad er fordelen ved en systemd-timer frem for cron?

Logs i journalctl, ingen anden kopi af et job, der stadig kører, indhentning med Persistent=true af kørsler, der blev misset, mens serveren var slukket, og en statuslinje med næste og seneste kørsel. Cron vinder på korthed: én linje i stedet for to filer.

Min timer gik 18 sekunder for sent. Hvorfor?

Som standard samler systemd timere inden for et vindue på et minut for at spare opvågninger; det er indstillingen AccuracySec. Vores timer hvert andet minut gik 07:42:18 i stedet for 07:42:00. Med AccuracySec=1s gik den præcis 07:46:00. Sæt den, når det præcise minut betyder noget.

Hvilken tidszone bruger cron og timere?

Serverens, som er UTC på vores images. Sæt den én gang med timedatectl, se vores guide om værtsnavn og tidszone, så følger både cron og timere den. En timer kan også have sin egen zone: OnCalendar=*-*-* 03:00 Europe/Kyiv kørte 01:00 UTC i vores test.

Kommentarer

Ingen kommentarer endnu. Vær den første.

Skriv en kommentar

Kommentarer modereres, før de vises.