wiki.phpfreakz.nl
Aanmelden Artikel Overleg Bewerk Geschiedenis Go to the site toolbox

Cron

door Sjors van der Pluijm (Bestuurslid)

Als je hoster gezegend is met een systeem uit de Unix familie heb je de mogelijkheid om taken op gezette tijden uit te voeren. Dat kan erg handig zijn voor het mailen van logbestanden, backups, etc. Uiteraard ben je wel afhankelijk van de goedheid van je hoster of je portemonnee, niet elke hoster zal cron standaard toestaan. Cron? Ja, de service heet cron, de taken noemen we cronjobs en de taken worden opgeslagen in de crontables. In dit artikel probeer ik uit te leggen hoe je cron moet gebruiken en waarom je het (meestal) helemaal niet nodig hebt. Heeft je hoster besloten om gebruik te maken van Windows dan heb je geen cron maar Task Scheduler. Dat is ook alles wat ik erover kwijt wil.

Inhoud

Wanneer wel, wanneer niet?

Misschien wel belangrijker dan de uitleg hoe je een cronjob maakt, zijn de redenen waarom je hem niet zou maken. Vaak wordt cron gebruikt voor toepassingen die helemaal geen cron vereisen omdat het helemaal niet nodig is dat die actie op gezette tijdstippen wordt uitgevoerd. Dit zijn meestal taken die volgens de maker elke minuut moeten gebeuren. Dat komt in de praktijk zeer zelden voor dus wanneer je zoiets aan de hand denkt te hebben dan is de kans groot dat je een denkfout maakt. Zo zul je bijvoorbeeld geen cron nodig hebben voor periodieke acties die niet periodiek uitgevoerd hoeven te worden, en sommige vormen van caching. Dat vraagt misschien om een kleine toelichting.

Periodieke acties die niet periodiek uitgevoerd hoeven worden? Dit zijn berekeningen of bewerkingen die wel worden uitgevoerd over een bepaalde periode maar waarvan het niet noodzakelijk is dat die berekening exact op dat tijdstip wordt gedaan.

Denk aan renteberekening; rente wordt berekend over een bepaalde periode zoals b.v. een maand. De clou is dat de renteberekening over Januari-2009 niet anders is wanneer je hem op 1-Feb-2009 om 0:00:00 doet of op 15-Maart-2009 om 15:09:25. De berekening is hetzelfde, de periode waarover je hem berekent is hetzelfde en dus is de uitkomst ook hetzelfde.

Een ander voorbeeld is het periodiek weggooien van records die niet meer gebruikt worden omdat ze ouder zijn dan b.v. een maand. Het maakt niet uit wanneer ze weggegooid worden want het systeem gebruikt ze toch niet. Ze moeten een keer worden weggegooid en dat hoeft niet exact 1 maand nadat ze gemaakt zijn, dat kan ook anderhalve maand daarna.

Een veelgebruikte niet-periodieke toepassing is het uitdelen van geld in een spel. In veel spellen verdienen de spelers elk uur geld uit hun illegale praktijken (in het spel dan he) en dus klinkt het logisch om dat ook echt elk uur te berekenen. Echter, de spelers zijn niet 24/7 online en je hebt het banksaldo van de speler eigenlijk alleen nodig wanneer de speler iets gaat kopen en dat doen ze naar verhouding zelden. Je kunt dus ook, net als bij de renteberekening, uitrekenen hoe lang geleden het geld voor het laatst is uitgekeerd en zoveel geld toevoegen. Is het drie uur geleden, dan krijgen ze 3x hun uurloon.

Een andere toepassing waarvoor cron niet gebruikt moet worden is het cachen van pagina's, afbeeldingen of templates. Althans, niet als kan worden bepaald of de cache verouderd is. Wil je bijvoorbeeld van een externe site, met toestemming van de eigenaar, een grafiek laten zien, dan kun je de grafiek met een bepaald interval downloaden en cachen op je eigen server. Dit doe je dan om de bezoeker niet te hinderen met het trage ophalen van de afbeelding. Ga je zelf je eigen HTML pagina's cachen, dan werk je niet met cron, maar laat je je script kijken of de gecachete pagina verouderd is. Dat kan bijvoorbeeld door te kijken naar de creatietijd van het cache bestand en de tijd van de laatste actie in de database. Afhankelijk daarvan maak je het cache bestand opnieuw en laat je het zien.

Als laatste valkuil voor cron zijn de scripts die blijkbaar elke minuut uitgevoerd moeten worden. Als je dit wil maak je zeer waarschijnlijk een denkfout en ben je bezig een periodieke actie periodiek uit te voeren terwijl dat niet hoeft. Is dat niet het geval, dan moet je nog steeds geen cron gebruiken maar kun je beter een daemon schrijven. Hoe dat moet kun je vast ergens op internet vinden.

Cron gebruik je dus voor acties die je periodiek wil uitvoeren en die ook periodiek uitgevoerd moeten worden. Voorbeelden hiervan zijn bijvoorbeeld het maken van backups van je scripts en de database of het maken van historische statistieken. Waar cron ook zeer geschikt voor is, zijn mailinglijsten en het mailen van rapporten of logbestanden van je site, waardoor je op gezette tijden automatisch op de hoogte wordt gebracht van de status van je website. Als laatste voorbeeld wil ik nog het opschonen van de database noemen, waarbij je moet letten op het verschil tussen opschonen en legen van de database. Onder opschonen valt het verwijderen van records die verouderd zijn of simpelweg niet meer nodig zijn, maar waarbij het wel of niet verwijderen ervan geen invloed heeft op de werking van de website. Vergeet ook niet dat een database geen problemen heeft met tabellen van miljoenen records.

Een leuke manier om te kijken of een hoster cron aanbiedt is kijken of de websites trager worden rond middernacht. Wat vaak gebeurt is dat mensen een cronjob laten uitvoeren om middernacht. Als maar genoeg webmasters dat doen, wordt de server vanzelf trager. Het is dus aan te bevelen de cronjob enkele minuten tot uren na middernacht uit te voeren. Als je je cronjob in de nacht van zaterdag op zondag uitvoert, hou dan rekening met zomer- en wintertijd. Bij het ingaan van de zomertijd zullen cronjobs tussen 2 en 3 uur niet worden uitgevoerd, bij het ingaan van de wintertijd worden ze dubbel uitgevoerd tussen 2 en 3 uur.

Hoe moet het dan?

Als je hoster je een mooi control panel voorschotelt is het niet al te moeilijk om een cronjob in te stellen, je moet alleen wel weten wat waar ingevoerd moet worden. Heb je SSH toegang tot de server, dan kun je het ook via de Command Line Interface (CLI) doen. Log in op de server en tik in:

crontab -e

Vervolgens zul je je crontable te zien krijgen in je favoriete editor, standaard is dat vi. Je kunt je favoriete editor wijzigen in het bestand .bash_profile, mits Bash je standaard shell is. Zet hiervoor aan het eind van het bestand:

export EDITOR=<editor>

De waarde van <editor> dien je natuurlijk te vervangen met de naam van de editor, zoals "pico", "vim", "emacs" of "nano", of een van de vele anderen. Je kunt deze regel uiteraard ook gewoon elke keer dat je hem nodig hebt intikken. De editor moet natuurlijk wel geïnstalleerd zijn en niet elke editor zal hiervoor geschikt zijn.

Maar of je nu via een control panel of een editor de crontable bewerkt, je zult dezelfde velden moeten invullen. Voor gewone stervelingen is de crontable opgedeeld in 6 kolommen:

<minuten> <uren> <dagen> <maanden> <weekdagen> <commando>

Deze 6 kolommen kun je weer opdelen in 2 groepen, namelijk het "wanneer" en het "wat". Het "wat" is het eenvoudigst, maar toch weer lastig. Het is namelijk gewoon een commando zoals je dat ook op de CLI zou kunnen opgeven. Op Unix systemen is cron een veelgebruikt programma om bijvoorbeeld logbestanden te archiveren. Je kunt voor <commando> dus alles invullen wat op de CLI ook werkt, mits de gebruiker die de cron uitvoert ook gerechtigd is om het programma uit te voeren. Je kunt hiermee dus bijvoorbeeld ook mysqldump uitvoeren om een backup van je database te maken, want dat doe je uiteraard niet met een PHP script. Let er op dat als je de inloggegevens van je database meegeeft aan mysqldump, dat deze dan tijdens het uitvoeren voor iedereen met toegang tot de CLI leesbaar kunnen zijn. Hoe je nu PHP scripts uit kan voeren met cron leg ik later uit. Het "wanneer" is dus verdeeld in 5 kolommen en elke kolom kan op dezelfde manier worden ingevuld. Voor het aangeven van de momenten waarop de cronjob moet worden uitgevoerd kun je gebruik maken van getallen, het sterretje (*) als wildcard, de komma (,) om waardes te plakken, het minteken (-) om een range aan te geven en de slash (/) voor intervallen. Aan de hand van wat voorbeelden wil ik duidelijk maken hoe je de cronjob kan instellen qua tijd.

1 2 3 4 5               Elke vrijdag (5) die op 3 april (4) valt om 1 minuut over 2
30 4 * * *              Elke dag om half 5 's nachts
30 4-6 * * *            Elke dag om half 5, half 6 en half 7
30 4-8/2 * * *          Elke dag om half 5, half 7 en half 9
30 4,6,8 * * *          Elke dag om half 5, half 7 en half 9
0 15,20 * */2 1-5       Wordt op werkdagen in de even maanden op elke dag (van de maand) uitgevoerd om 15:00u en om 20:00u.
*/10 8-16,22 * * *      Het commando wordt elke 10 minuten uitgevoerd tussen 8:00u en 16:59u en tussen 22:00u en 22:59u.

PHP uitvoeren

Als je PHP bestanden wil gaan uitvoeren via een cronjob kan dat op twee verschillende manieren. De meest makkelijke en efficiënte manier is het direct uitvoeren van het script via de parser. Hiervan zijn twee varianten. Een andere, wat minder elegante, methode is het simuleren van de browser.

Het script uitvoerbaar maken

Voor deze methode en de volgende zul je moeten weten waar de PHP parser staat. Als je SSH toegang hebt kun je deze zelf zoeken (find / -name php) en anders zul je een mailtje moeten sturen aan je hoster. In je PHP script kun je aangeven waar de parser staat en je shell zal je script aan de parser doorgeven. Zet hiervoor op de eerste regel van je script een shebang (#!), gevolgd door het pad naar de PHP parser, wat vaak /usr/bin/php is.

#!/pad/naar/php

Vervolgens moet je het script nog uitvoerbaar maken. Hoe dit moet hangt een beetje af van de indeling van het systeem en kun je daarom beter in overleg met je hoster doen. Wil je dit zelf doen, lees dan eerst een artikel over het rechtensysteem van Linux of Unix, maar in het kort doe je dit met:

$ chmod +x bestandsnaam

Het voordeel van deze methode is dat je het script ook buiten de document root kan zetten, waardoor het niet meer via een webbrowser uit te voeren is. Voor het commando in de cronjob geef je het absolute pad naar het script op:

10,20 */2 * * * /pad/naar/php/script

Direct aan de parser voeren

Deze methode is bijna gelijk aan de vorige. Het enige verschil is dat je het pad naar de PHP parser opgeeft bij het commando voor de cronjob. Deze methode biedt het voordeel dat je ook extra parameters mee kan geven aan de parser. Zo kun je bijvoorbeeld safe_mode uitzetten of andere instellingen wijzigen. Hoe dat moet kun je vinden op de manpage (zoek op "man php") van PHP vinden. Bijvoorbeeld:

30 4 * * 1-5 /pad/naar/php /pad/naar/php/script.php

Je hoeft het PHP script dan niet uitvoerbaar te maken maar kunt het nog wel buiten de document root zetten.

Wget

Weet je niet waar de PHP parser staat of heb je bepaalde zaken nodig die de webserver je biedt, dan kun je tenslotte nog een webbrowser nadoen met Wget. Met het programma wget kun je een pagina opvragen en dus je script uitvoeren. Deze methode werkt niet altijd, niet alle hosters staan het gebruik van wget toe en je moet wel weten waar dit programma staat. Meestal is dat overigens /usr/bin/wget. Bedenk wel dat deze methode nogal een omweg is: je moet het script opvragen via wget, die de webserver moet raadplegen die op zijn beurt de PHP parser aanspreekt.

*/10 9 * 1-6 * /pad/naar/wget -O /dev/null -q http://www.url.nl/script.php

Met het argument -O /dev/null vertel je dat wget de output van je script moet schrijven naar de prullenbak, met -q geef je aan dat je geen foutmeldingen wil zien.

Nadeel is, dat iedereen die weet hoe die scripts heten, ze via een browser kan oproepen en je taken op verkeerde momenten, of veel te vaak kan starten. 50 gelijktijdig lopende backupscripts van je database zijn vast geen pretje.

Een oplossing is het beveiligen van de scripts of de directory waarin deze staan met een password via een Htaccess bestandje.

De username en password geef je mee middels

/pad/naar/wget --http-user=gebruikersnaam --http-passwd=wachtwoord http://www.url.nl/script.php

Site Toolbox:

Persoonlijke hulpmiddelen
De laatste wijziging op deze pagina vond plaats op 23 jan 2010 15:33. - Deze pagina werd 2.519 maal bekeken. - Disclaimers - Over PFZWIKI