PHP exec_shell geeft een 504 gateway timeout
Ik heb dus
Code (php)
1
$result = shell_exec('php '.DOC_ROOT.'downloader/progressbar.php '.$_GET['term'].' '.$time.'');
Het werkt bij kleine processen wel goed, maar bij grote processen, duurt het some uren en krijg ik een 504 gateway timeout.
Wat ik eigenlijk wil weten is
1) Wat zijn de verschillen van shell_exec in PHP VS CLI? In cli werkt het wel gewoon prima, in een cronjob ook.
2) Hoe zet ik als een gebruiker bijv. op een knop in de browser klikt, een taak in de cronjob?
Via de exec_shell krijg ik dus niet hetzelfde resultaat als met de cli,
Wat zal hier een oplossing voor zijn?
Ik vermoed dat het met de max_execution_time te maken heeft.
escapeshellarg($_GET['term']), anders kan iedereen van alles injecteren ...
En on-topic: CLI kent standaard geen time-out, en maakt dus (standaard) altijd alles af (hoe lang het ook duurt). Via Apache (of wat je dan ook als webserver gebruikt) geldt er (standaard) wel een time-out (meestal 30 of 60 seconden). En als je script wel (langer) doorloopt kan het zijn dat Apache (Nginx, enz) na een tijdje het wel mooi geweest vindt en (alvast) een 504 terugstuurt (ondanks dat je script dus nog wel door aan het ploeteren is).
Misschien ook even een En on-topic: CLI kent standaard geen time-out, en maakt dus (standaard) altijd alles af (hoe lang het ook duurt). Via Apache (of wat je dan ook als webserver gebruikt) geldt er (standaard) wel een time-out (meestal 30 of 60 seconden). En als je script wel (langer) doorloopt kan het zijn dat Apache (Nginx, enz) na een tijdje het wel mooi geweest vindt en (alvast) een 504 terugstuurt (ondanks dat je script dus nog wel door aan het ploeteren is).
Gewijzigd op 28/03/2021 14:29:48 door Rob Doemaarwat
je knop in de website roept een script aan dat op een zekere plek een bestand plaatst. Bijvoorbeeld "doe-printer.txt"
Jouw cronjob draai je elke minuut. (bijvoorbeeld)
Treft het script van je cronjob het bestand doe-printer.txt op de afgesproken plek aan, dan begint hij aan de uitvoering van (in mijn geval) een printer gerelateerde opdracht. (die ik met root rechten moet uitvoeren).
Je cronscript moet dan ook na afloop of direct het txt bestandje opruimen.
Eventueel kun je in het bestand nog parameters kwijt, afhankelijk van wat je aan wilt roepen.
Let er wel op dat je niet op een gegeven moment 24 van die uitvoeringen gelijktijdig hebt lopen.
Dat voorkom je door bijvoorbeeld naast doe-printer.txt ook een bezig-met-printer.txt te plaatsen in je cron-script.
Al dan niet voorzien van bijvoorbeeld het process-id van de cronjob.
Daarmee zien andere aanroepen dat er al gewerkt wordt, en dat het niet nodig is om nog een keer de opdracht uit te voeren.
Met name van belang als je runtime > 1 minuut is.
Ik had zoals idd ook bedacht in de dbase. Als de database bezig is dat er een kolom "bezig" op 1 komt te staan.
Elke 10 min een corn die ernaar kijkt, als er 1 proces op 1 staat dat hij hem niet uitvoer.
Ik dacht wellicht dat er een betere manier was, maar dit zal het moeten doen.
Zoals je al zei, de jobs duren wat langer... Als de job incidenteel langer duurt dan het cron interval (bijv 1 minuut) dan loop je de kans dat de job nogmaals opgestart wordt en nogmaals en nogmaals. Je kan dit inderdaad verfijnder oplossen met behulp van een tabel en wat parameters. In de tabel zet je dan de scriptnaam van het uit te voeren script en bijvoorbeeld een numeriek attribuut dat de status aangeeft. 1=wacht op behandeling, 2=actief, 3=afgerond etc en de cron hoeft dan alleen maar te kijken naar jobs met status=1. Je kan het record uiteraard uitbreiden met datum/tijd start en klaar etc zodat je ook wat logging hebt over de uitvoering. Zelfs foutmeldingen kan je dan opnemen.
Gewijzigd op 30/03/2021 20:48:36 door Aad B
webSocket aan kunnen roepen. Dan heb je geen last van time-outs, en kun je de browser tijdens het verwerken van de taak ook nog "op de hoogte houden" (hoe ver ie is met het verwerken, evt. tussenresultaten, enz). Werkt op zich heel mooi, maar wel een kleine leercurve waar je eerst doorheen moet, en je moet wat "vrijheden" op je server hebben (poort open zetten voor WebSocket verkeer, en uitluisteren via je eigen - continu draaiende - PHP script).
Werkt op zich heel mooi, en met instant feedback. Maar als dat laatste niet echt een "nice to have" is, dan zou ik ook gewoon voor de "tabel met taken" aanpak gaan. Overigens is het geen probleem als de cron meerdere malen gestart wordt, als je maar zorgt dat elke taak eenduidig "gelockt" wordt (zodat een parallel proces = de job die een minuut eerder/later is ingestart 'm niet ook oppakt). En houd er rekening mee dat dingen ook wel eens fout kunnen gaan, en dat een job dan tot in lengte van dagen gelockt blijft. Dan moet niet je hele afhandeling (ook andere jobs) tot stilstand komen (maar een keer ergens een waarschuwing van "job x al zoveel minuten gelockt", en 'm dan "opzij zetten").
Eventueel zou je "de lange taak" ook via een Werkt op zich heel mooi, en met instant feedback. Maar als dat laatste niet echt een "nice to have" is, dan zou ik ook gewoon voor de "tabel met taken" aanpak gaan. Overigens is het geen probleem als de cron meerdere malen gestart wordt, als je maar zorgt dat elke taak eenduidig "gelockt" wordt (zodat een parallel proces = de job die een minuut eerder/later is ingestart 'm niet ook oppakt). En houd er rekening mee dat dingen ook wel eens fout kunnen gaan, en dat een job dan tot in lengte van dagen gelockt blijft. Dan moet niet je hele afhandeling (ook andere jobs) tot stilstand komen (maar een keer ergens een waarschuwing van "job x al zoveel minuten gelockt", en 'm dan "opzij zetten").
Laminas (vroeger Zend) heeft daar een implementatie van.
Als je erg vaak gaat pollen is het wel beter om een websocket op te zetten, anders word de overhead/load van een volledige HTTP call wel wat veel.