Hallo,

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.

<?php
set_time_limit(0);
ignore_user_abort(true);
?>


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.
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.

<?

$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
<?
$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? :/
Misschien dat het een bestaand script is, waarbij de maker natuurlijk niet kan weten of iemand kan 'ontsnappen' uit zijn webroot. Maar ik blijf er bij dat zulke ranzige checks overbodig zijn, en dat crons buiten de webroot moeten worden gedraaid, of anders in een dichtgetimmerde directory in de webroot.
Dan hoef je met PHP niks meer dicht te timmeren.
Dat stukje code had ik bij Stackoverflow (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.

[size=xsmall]Toevoeging op 21/03/2017 15:27:09:[/size]

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.

<?php

echo "a";

$url = "http://url.nl/$i";
$output = file_get_contents($url);

echo "b";

$con = mysqli_connect(- - - -);
if (!$con) {die("Connection failed: " . mysqli_connect_error());}

echo "c";

?>

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.
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
301816 / 1024 = 294,7421875 MB
Ik maak een foutje, sorry.

Reageren