Cronjob PHP-script stopt soms voortijdig (update)
Ik heb een PHP-script gemaakt dat wordt uitgevoerd dmv een cronjob, maar hij stopt soms voortijdig op onverklaarbare wijze. Ik gebruik een for-loop om data te scrapen (niks illegaals) van pagina's die vrijwel identiek zijn. Als het script is afgerond krijg ik dan een mail met hoeveel pagina's hij heeft nagelopen. 9 van de 10 keer gaat het perfect, maar soms komt het dus voor dat hij het eind van het script niet haalt, en maar een beperkt deel van het aantal loops uitvoert. Als ik dan kijk bij welk nummer hij is gestopt dan is daar geen aanwijsbare reden voor te vinden.
Ik had al wat nagezocht en het volgende in de code gestopt om een timeout te voorkomen.
Ik zal de hele code besparen, het is ook niet veel bijzonders, maar de loop ziet er als volgt uit. In elke loop maak ik opnieuw connectie met de database zodat die geen timeout geeft.
- Connectie maken met MySQL database
- Data escapen
- Data invoeren
- Updaten in database welke hij laatst heeft gehad
- Connectie verbreken
Ik heb de opdracht opgeknipt in brokjes, maar wat zou de reden kunnen zijn dat hij tussentijds stopt? En is er een mogelijkheid om dat in die mail terug te kunnen zien? Kan het nog steeds door connectie-verlies komen? Een error bij de betreffende insert lijkt me onmogelijk, en dan moet hij volgens mij ook gewoon verdergaan. De laatste keer stopte hij al na 30 loops, terwijl hij er normaal 5000 doet. Hij doet ongeveer vijf loops per seconde.
Ik heb de cronjob ingesteld vanuit DirectAdmin, dus die hele technische taal mbt de cronjob/logs etc en waar ik dat zou moeten invullen is me niet helemaal eigen.
Ik hoop dat jullie me kunnen helpen.
Gewijzigd op 21/03/2017 15:31:21 door G Jansma
Voer je het script dus direct aan PHP, of laat je het via bijv. wget eerst nog via de webserver lopen?
- Ariën - op 20/03/2017 15:49:39:
Hoe voer je de cornbjob uit? Met welk commando?
Voer je het script dus direct aan PHP, of laat je het via bijv. wget eerst nog via de webserver lopen?
Voer je het script dus direct aan PHP, of laat je het via bijv. wget eerst nog via de webserver lopen?
Gewoon in DirectAdmin ingevoerd met die sterretjes. En bij command staat:
/usr/local/bin/php -q -f/home/username/domains/domeinnaam.nl/public_html/phpdocument.php
Direct aan PHP dus. Heb je al de output naar een log geschreven?
En vooral: staat error reporting (en display_errors) aan (borkt hij niet gewoon op geheugen)?
Wat Ben zegt, en dan de boel goed loggen! Desnoods ook even het geheugen timen, en kijken of hij daar ergens op spaak loopt.
@Ariën: Nee. Ik las dat het verstandig was om een log te hebben van wat de cronjob doet. Maar die 'html' van de pagina stuurt hij naar de mail, dat is de log?
@Ben: Volgens mij wel, maar dat kan ik voor de zekerheid aanzetten met onderstaande?
En wat betekent 'borkt hij niet gewoon op het geheugen'?
@Ariën2: Zou je misschien kunnen uitleggen hoe dat moet?
Gewijzigd op 20/03/2017 16:38:53 door G Jansma
>> En wat betekent 'borkt hij niet gewoon op het geheugen'?
Schiet je niet gewoon door de geheugenlimiet?
Tevens raad ik niet aan om cronjobs in de public_html te plaatsen. Je wilt toch niet dat jan en alleman ze kunnen uitvoeren?
Ben van Velzen op 20/03/2017 16:47:03:
Je kunt het gewoon met de standaard reporting regels aanzetten ja. Vaak is de cli php configuratie anders dan de web configuratie, dus het is altijd mogelijk dat cronjobs afwijken van websites.
>> En wat betekent 'borkt hij niet gewoon op het geheugen'?
Schiet je niet gewoon door de geheugenlimiet?
>> En wat betekent 'borkt hij niet gewoon op het geheugen'?
Schiet je niet gewoon door de geheugenlimiet?
Ik heb er niet veel verstand van, maar dat denk ik niet. Volgens mij is er niet veel geheugen benodigd voor wat ik doe. Zou zoiets ook als error worden gemeld? En hoe valt dat te meten/timen?
@Ariën: Daar zit wat in, maar als beginner zet ik alles in public_html. In welke map zou ik dat moeten zetten dan, of kan je een cronjob in elke map zetten? Ik had dat probleem met onderstaande PHP gedicht.
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?
$sapi_type = php_sapi_name();
if(substr($sapi_type, 0, 3) == 'cli' || empty($_SERVER['REMOTE_ADDR'])) {
//En de rest van de code hier
}
?>
$sapi_type = php_sapi_name();
if(substr($sapi_type, 0, 3) == 'cli' || empty($_SERVER['REMOTE_ADDR'])) {
//En de rest van de code hier
}
?>
Gewijzigd op 20/03/2017 17:14:51 door G Jansma
Als je reporting aan hebt staan wel, anders stopt je script op een ogenschijnlijk willekeurig moment. Je kunt het meten door regelmatig memory_get_peak_usage aan te roepen, en dit te vergelijken met je memory_limit.
Gewijzigd op 20/03/2017 17:18:09 door Ben van Velzen
G Jansma op 20/03/2017 17:08:49:
@Ariën: Daar zit wat in, maar als beginner zet ik alles in public_html. In welke map zou ik dat moeten zetten dan, of kan je een cronjob in elke map zetten? Ik had dat probleem met onderstaande PHP gedicht.
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?
$sapi_type = php_sapi_name();
if(substr($sapi_type, 0, 3) == 'cli' || empty($_SERVER['REMOTE_ADDR'])) {
//En de rest van de code hier
}
?>
$sapi_type = php_sapi_name();
if(substr($sapi_type, 0, 3) == 'cli' || empty($_SERVER['REMOTE_ADDR'])) {
//En de rest van de code hier
}
?>
Opsich zou dit kunnen werken, maar voor de zekerheid zou ik het buiten je /public_html plaatsen. Een mapje hoger zou kunnen. Eventueel kan je ook met .htaccess alle toegang tot de directory via de webserver afvangen als je binnen je /public_html wilt blijven. Met PHP kan je er toch wel bij komen omdat het via het file-systeem gaat.
Om even duidelijkheid te schappen in de term 'cronjob'. Dit is de taak zelf die je aanmaakt in Directadmin (of via crontab -e in de CLI). Wat je laat uitvoeren is altijd het script.
G Jansma op 20/03/2017 17:08:49:
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?
$sapi_type = php_sapi_name();
if(substr($sapi_type, 0, 3) == 'cli' || empty($_SERVER['REMOTE_ADDR'])) {
//En de rest van de code hier
}
?>
$sapi_type = php_sapi_name();
if(substr($sapi_type, 0, 3) == 'cli' || empty($_SERVER['REMOTE_ADDR'])) {
//En de rest van de code hier
}
?>
Dus eerst zet je je code op een onhandige plaats, en vervolgens timmer je het gat dat je op deze manier zelf creëert weer dicht? :/
Dan hoef je met PHP niks meer dicht te timmeren.
http://stackoverflow.com/questions/190759/can-php-detect-if-its-run-from-a-cron-job-or-from-the-command-line) gevonden. Was dus wel iets waar ik over had nagedacht om het af te schermen, maar zal in het script voor een Cronjob (ik zal het terminologisch goed proberen te doen) in een map hoger zetten. Weer wat geleerd.
Ik ga die memory usage erin zetten, de errors allemaal aan en dan loggen, en dan zie ik wel of het weer gebeurd. In de laatste 20x ging het iets van 2x fout, dus het zal vast nog wel eens misgaan.
Bedankt voor de hulp allen, ik laat het wel weten wat eruit komt.
Toevoeging op 21/03/2017 15:27:09:
Update
Nou, hij is inmiddels drie keer voortijdig gestopt. Helaas geeft hij geen error op het moment dat hij stopt in de output. Na de eerste keer heb ik maar geprobeerd om iets beter te kunnen lokaliseren waar het mis ging door middel van wat extra echo's.
De eerste keer ging het mis tussen a en b (na 3000 loops), de tweede keer tussen b en c (na 400 loops). Beide keren zonder error. En bij die eerste keer ligt het ook niet aan de pagina, want als ik hem opnieuw opstart gaat hij daar vrolijk verder. En als de connectie was gefaild had hij een error moeten geven. Het lijkt me een beetje random waar hij ermee stopt.
Ook aan de memory_peak_usage kan het volgens mij nooit liggen. Ik echo die elke loop, maar was in de eerste 301816 en in de tweede 300056 terwijl de memory_limit 256MB is zegt ie.
Waar zou het dan aan kunnen liggen? En zijn er mogelijkheden om nog beter te loggen? Ik las iets met '2>&1' maar ik heb geen idee waar ik dat zou moeten invoeren, en waar ik dat dan terug zou kunnen vinden.
Dat stukje code had ik bij Stackoverflow (Ik ga die memory usage erin zetten, de errors allemaal aan en dan loggen, en dan zie ik wel of het weer gebeurd. In de laatste 20x ging het iets van 2x fout, dus het zal vast nog wel eens misgaan.
Bedankt voor de hulp allen, ik laat het wel weten wat eruit komt.
Toevoeging op 21/03/2017 15:27:09:
Update
Nou, hij is inmiddels drie keer voortijdig gestopt. Helaas geeft hij geen error op het moment dat hij stopt in de output. Na de eerste keer heb ik maar geprobeerd om iets beter te kunnen lokaliseren waar het mis ging door middel van wat extra echo's.
Code (php)
De eerste keer ging het mis tussen a en b (na 3000 loops), de tweede keer tussen b en c (na 400 loops). Beide keren zonder error. En bij die eerste keer ligt het ook niet aan de pagina, want als ik hem opnieuw opstart gaat hij daar vrolijk verder. En als de connectie was gefaild had hij een error moeten geven. Het lijkt me een beetje random waar hij ermee stopt.
Ook aan de memory_peak_usage kan het volgens mij nooit liggen. Ik echo die elke loop, maar was in de eerste 301816 en in de tweede 300056 terwijl de memory_limit 256MB is zegt ie.
Waar zou het dan aan kunnen liggen? En zijn er mogelijkheden om nog beter te loggen? Ik las iets met '2>&1' maar ik heb geen idee waar ik dat zou moeten invoeren, en waar ik dat dan terug zou kunnen vinden.
Gewijzigd op 21/03/2017 15:27:57 door G Jansma
Als dit bytes zijn: 301816, dan is dat toch meer dan 256MB?
- SanThe - op 21/03/2017 15:40:44:
Als dit bytes zijn: 301816, dan is dat toch meer dan 256MB?
Volgens die PHP.net is memory_get_peak_usage in bytes.
301 816 bytes =
0.301816 megabytes
Ik maak een foutje, sorry.
Gewijzigd op 21/03/2017 15:56:28 door - SanThe -