Autor Zpráva
ehlo_f1re
Profil *
Zdravim,

hledám způsob jak spustit script z PHP a realtimově zpracovávat nové řádky na výstupu. Příklad pseudokódu:
spustit_script_se_zpracovanim_novych_radku("/cesta/ke/skriptu.sh", "nazev_funkce_zpracovavajici_nove_radky");

function nazev_funkce_zpracovavajici_nove_radky($radek){
zpracuj_nejak($radek);
}
Můj cíl je spustit script, který má dlouhé vykonávání a není možno čekat na vypsání až do konce. Chci přes webový socket javascriptem zobrazovat výstup na stránce. A právě v PHP se spustí funkce která nový řádek zašle klientovi. Pokud má někdo lepší řešení tak uvítám. :)


Zapoměl jsem to ujasnit. V PHP pseudokódu tedy požaduji, aby se "sledovalo" jestli na výstupu /cesta/ke/skriptu.sh neobjevil nový řádek. Pokud ano, tak se npř. spustí funkce nazev_funkce_zpracovavajici_nove_radky a jako argument jí bude předán nový řádek.


Neví tedy někdo prosím jak to udělat? Nějaký hint? Díky za odpovědi!
MartinP_
Profil *
Co na to použít nějaký jiný jazyk, než PHP? V jiných jazycích, které nespouštějí nový proces při každém požadavku můžeš sledovat výstup stdoutu a podle toho posílat data na websocket. Je to práce na pár řádků.

Jestli to ale chceš v PHP, musel bys program spustit na pozadí a výstup přesměrovat do souboru nebo fifo (pojmenovaná roura) a pak pomocí časovače přečíst řádek, zpracovat ho a odeslat klientovi.

<?php
  if(!prikaz_bezi()) { // zkontroluje např. existenci fifo souboru apod.
    posix_mkfifo("./roura", 0644); // vytvori rouru
    exec("prikaz > ./roura &"); // spustí příkaz, stdout přesměruje do vytvořené roury
  }
  
  $fd = fopen("./roura", "r");
  stream_set_timeout($fd, 1); // bude cekat max 1s na radek z programu, pak selze
  $radek = fgets($fd);
  fclose($fd);
  
  if($radek)
    echo $radek;
?>

Tento PHP skript budeš volat AJAXem z časovače, při prvním spuštění spustí program na pozadí a pak bude postupně vracet řádky výpisu. Zkoušel jsem to, ale ještě to chce vyladit, protože to některé řádky přeskakuje.
ehlo_f1re
Profil *
Časovač a ajax použít nechci. :)
Zatim to také vidím na jiný jazyk pro tuto část. Ale bylo by pěkné to mít celé v PHP.
MartinP
Profil *
Můžeš také program rovnou přesměrovat do php:
./soubor.sh | php zpravuj.php; # toto můžeš dát klidně do exec() v jiném PHP skriptu

zpracuj.php:
<?php
  $fd = fopen("php://stdin", "r");
  while($radek = fgets($fd)) {
    zpracuj($radek);
  }
?>
Alphard_
Profil *
Na tohle se používá proc_open().
ehlo_f1re
Profil *
Toto mi funguje zatím perfektně.
$pip = popen($cmd, "r");
while( $line = fgets($pip) ){
    echo  $line;
    delej_neco_s_radkem($line);
}

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: