Autor | Zpráva | ||
---|---|---|---|
mckay Profil |
Půjde o trochu složitější dotaz, nechci ho však dělit do více vláken, takže se pokusím o co nejvýstižnější popis + úvahy na toto téma.
Prostředí: Mám k dispozici linuxový server, na kterém nemám root oprávnění, ale většinu operací dělat můžu. Je na něm php, které budu spoustět příkazem v terminálu nad mým skriptem. Skript by měl být schopen běžet nekonečně dlouhou dobu, docíleno toho bude stylem while (true) Run(); . Reálně však vím, že se server každé pondělí v 0600 restartuje a proto budu mít zařízené, že se potom skript i znovu spustí (automatizovaným externím ssh připojením a nahozením skriptu znovu, CRON na tomto serveru k dispozici bohužel nemám).
Prohledal jsem diskusi vztahující se k tomuto tématu a narazil na vlákno z roku 2012, kde se mezi Alphardem a Keeehim rozhořela krátká diskuse na téma, zda php je na tento typ práce postavené, nebo ne. Závěr není úplně jednoznačný, ze zběžného progooglení jsem také zahlédl spíše dohady a empirické zkušenosti, ale staršího data. 1. Jaká je situace teď a jaké jsou Vaše empirické zkušenosti nyní? Pomocí tohoto skriptu chci v určitých intervalech spouštět další php skripty, které mohou být i dlouhodobějšího charakteru. Procrawlování celého webu, vytažení subjektivně zajímavých informací, statistické zpracování dat dotažených z konkrétních zdrojů, upozornění emailem apod. Co tedy chci je, aby skript při každé iteraci cyklem podmíněně vypálil další proces (spuštění dalšího php skriptu), který provede svou práci a nějakým způsobem dá volajícímu skriptu vědět, že práci dokončit (s nějakým výstupem / exit kódem / návratovou hodnotou). Z hlediska jazyka k tomuto pravděpodobně použiji exec() nebo system() funkci. Jak ale dám od spouštěného skriptu vědět skriptu, ze kterého byl spuštěn, že byla práce dokončena. Příklad scénáře: 1. Projíždím cyklem poprvé a startuji další skripty: skript1.php skript2.php + uspávám hlavní skript na 5 sekund, 2. skript2.php se stihne dokončit (a dá vědět, že se dokončil - Otázka 2: Jak dá vědět, že se dokončil?), skript1.php se nestihne dokončit a nijak vědět nedá, 3. Cyklus iteruje podruhé a ví, že skript2.php se dokončil a tedy ho pouští znovu. Ví, že skript1.php stále pracuje a tedy ho znovu nepouští a usíná na 5 sekund, 4. skript1.php a skript2.php se dokončují a dávají vědět, že jsou dokončeny 5. Cyklus iteruje potřetí a ví, že má pustit oba skripty znova... což taky udělá a zase spí. A takhle dokola. Jsem otevřen i více technickým řešením a workaroundům, kdy pokud neexistuje v jazyce mechanismus na výše popsaný scénář, bude možné tuto funkcionalitu naprogramovat (např. nějakým rozumným způsobem zapisováním do souboru o stavu operace a kontrolou těchto souborů při každé iteraci). Suma sumárum 2 otázky, těším se na Vaše odpovědi. Edit: Napadla mě v souvislosti s tímto ještě jedna věc - co se stane, pokud po naincludeování souboru do toho dlouho běžícího skriptu, includeovaný soubor smažu? |
||
Keeehi Profil |
#2 · Zasláno: 2. 10. 2016, 21:44:08
mckay:
Pokud vím, tak exec a system jsou synchronní. Takže čekají, než skončí program, který volali. Ten volaný program se dá spustit na pozadí, tím že se na konec přidá & ale v tom případě se s ním asi nedá dále komunikovat (kromě postraních kanálů, jako třeba přes soubory, fronty nebo databázi).
Podíval bych se na pcntl_fork a další funkce z rodiny pcntl_* které umožňují nakolonování procesu kde v jednom vlákně bude běžet ta řídící smyčka a v jiných si php spusí synchonní exec. Vlákna si mezi sebou umí posílat zprávy (v PHP jsem to nikdy nedělal) a nebo na sebe vyčkávat. Celé je to pak velká sranda, když jeden proces čeká na druhý zatímco on čeká na ten první, nebo když více procesů přistupuje k stejnému prostředku (např. souboru) a jiné. Také se to perfektně debuguje, když chyba se projeví jen občas, protože se dva procesy zrovna náhodou potkají. No, užiješ si :) |
||
Jan Tvrdík Profil |
#3 · Zasláno: 3. 10. 2016, 13:49:31
mckay, Keeehi:
Asynchronní pouštění procesů se dělá přes proc_open. mckay: Proč to nechceš řešit normálně (tj. přes nějakou frontu)? |
||
Časová prodleva: 8 let
|
0