Cronjobs og Flock
Sådan forhindre du Cronjobs i at overlappe hinanden
Har du en Linux-server? og afvikler du løbende cronjobs fra denne Linux-server? Hvis du kan svare Ja til de to overstående spørgsmål, er jeg sikker på du også kender til problemet med at forhindre cronjobs i at overlappe hinande? Jeg har hvertfald ofte fået netop dette spørgsmål fra brugere her på v5.dk.
Problemet kort fortalt
Du har planlagte opgaver (cronjobs) på din server, måske et job der kører hvert 10. minut, men en eller anden dag, tager jobbet måske længere tid at udføre end forventet, dette betyder i sidste ende, at dine jobs begynder at overlappe hinanden og køre på samme tid. Hvis dine cronjobs, handler på de samme data fra eksempelvis en MySQL-database, kan det betyde data-korruption; måske bliver betalinger gennemført flere gange? måske bliver data dobbelt-bogført i dit regnskabssystem, måske bliver der udsendt flere mails end nødvendigt - der kan være mange konsekvenser af overlappende cronjobs.
Løsningen på overstående problem er heldigivs simpel!
Jeg har set rigtig mange eksempler på at løse dette problem. Oftest har jeg set en MySQL-database med et KørerMitScript-felt sat til true eller false, og på den måde styrer om et job kører eller ej, der er mange grunde til hvorfor dette bestemt ikke er en smart løsning, men der er ingen grund til at genopfinde den dybe tallerken, når den allerede findes, og samtidig er gratis
Si' hej til Flock
Flock er et meget interessant værktøj til styring at låste filer. Disse låste filer bruges til at afgøre, om er script eller program allerede kører (kan sammenlignes med en PID-fil, der indeholder et Proces ID på det kørende script). Hvis låsen eksisterer, vil jobbet ikke starte. Hvis låsen ikke eksisterer, er det sikkert at starte cronjobbet op.
Lad os tage et simpelt eksempel her, hvor der hvert minut eksekveres et PHP-script:
$ crontab -l
* * * * * /usr/bin/php /var/cron/php/v5-book-economic.php
I overstående eksempel køres v5.dks faktura-motor hvert minut, men nogle gange er e-conomics lidt længere om at svare, derfor er det vigtigt at vores script ikke overlapper, men det er heldigvis super nemt at løse vha. flock, her er et eksempel:
$ crontab -l
* * * * * /usr/bin/flock -w 0 /tmp/v5booke.lock /usr/bin/php /var/cron/php/v5-book-economic.php
Så ved blot at indsætte /usr/bin/flock -w 0 /tmp/v5booke.lock foran vores normale cronjob, har vi nu sikret at jobbet ikke kan overlappe sig selv.
Installation af Flock
Overstående eksempel kræver naturligvis at Flock er installeret på din Linux-server. Hvis du kører Ubuntu- eller Debian Linux skriver du blot apt-get install flock
for at installerer flock, på CentOS er kommandoen yum install flock
.
Tjek om en process er låst
Når overstående eksempel køres, låses filen /tmp/v5booke.lock så længe vores PHP-script arbejder. For at se om en process er aktiv og dermed om filen er låst, kan kommandoen fuser bruges, som viser hvilken bruger og hvilken PID der har låst lock-filen.
$ fuser -v /tmp/v5booke.lock
USER PID ACCESS COMMAND
cron.lock: crnjbs 7836 f.... flock
crnjbs 7837 f.... php
Hvis overstående fuser-kommando ikke returnerer nogle users, er cronjobs frit, og bliver eksekveret igen ved næste cron-kørsel.
Konklussion
Jeg håber dette har givet et godt lille eksempel på hvordan man nemt kan bruge flock til at forhindre cronjobs i at overlappe hinanden.
Har du har et spørgsmål er du mere end velkommen til at oprette det i vores forum. Kommentarer, feedback og gode idéer kan skrive i kommentar-feltet under her.
God fornøjelse med flock