PHP exec_shell geeft een 504 gateway timeout

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Daniel van Seggelen

Daniel van Seggelen

28/03/2021 14:15:51
Quote Anchor link
De titel zegt het al.

Ik heb dus
Code (php)
PHP script in nieuw venster Selecteer het PHP script
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?
 
PHP hulp

PHP hulp

09/05/2021 22:41:46
 
- Ariën -
Beheerder

- Ariën -

28/03/2021 14:20:59
Quote Anchor link
Ik vermoed dat het met de max_execution_time te maken heeft.
 
Rob Doemaarwat

Rob Doemaarwat

28/03/2021 14:26:27
Quote Anchor link
Misschien ook even een 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).
Gewijzigd op 28/03/2021 14:29:48 door Rob Doemaarwat
 
Ivo P

Ivo P

28/03/2021 15:04:19
Quote Anchor link
alternatief:

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.
 
Daniel van Seggelen

Daniel van Seggelen

28/03/2021 18:45:01
Quote Anchor link
Bedankt Ivo,

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

Aad B

30/03/2021 20:43:42
Quote Anchor link
Inderdaad, via een tabel oplossen.
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
 
Rob Doemaarwat

Rob Doemaarwat

30/03/2021 21:42:52
Quote Anchor link
Eventueel zou je "de lange taak" ook via een 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").
 
Thom nvt

Thom nvt

01/04/2021 08:34:30
Quote Anchor link
Voor een voortgangsindicatie hoef je niet persé een websocket te gebruiken, dat kan ook via polling middels AJAX:
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.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.