[php] stdin / proc_open

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

Anoniem: 80910

Topicstarter
Stel ik heb een programma die ik wil draaien in een ander programma en het programma heeft een prompt, hoe krijg ik de prompt goed in het andere programma.

ik heb een execute function met deze inhoud:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static function execute($command, &$output = '', &$error = '', $type = null)
$descriptorspec = array(
                0 => array("file", 'php://stdin', "r"),  // stdin
//                0 => array("pipe", "r"),  // stdin
                1 => array("pipe", "w"),  // stdout
                2 => array("pipe", "w"),  // stderr
            );
            $process = proc_open($command, $descriptorspec, $pipes, Dir::current(), null);
            $output = stream_get_contents($pipes[1]);
            fclose($pipes[1]);

            $error = stream_get_contents($pipes[2]);
            fclose($pipes[2]);
            if(ob_get_level() > 0){
                ob_flush();
            }
            return proc_close($process);
}



dan voer ik in een ander script termninal.readline uit die er ongeveer zo uit ziet:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public static function read($url='', $text=''): ?string
    {
        $is_flush = false;
        if(ob_get_level() > 0){
            $is_flush =true;
        }
        if($is_flush){
            ob_flush();
        }
        if(empty($url)){
            $url = 'input';
        }
        $input = null;
        if($url === 'input'){
            fwrite(STDOUT, $text);
//            echo $text;
            if($is_flush){
                ob_flush();
            }
            $input = trim(fgets(STDIN));
            echo PHP_EOL;
        }
        elseif($url === 'input-hidden'){
//            echo $text;
            fwrite(STDOUT, $text);
            if($is_flush){
                ob_flush();
            }
            system('stty -echo');
            $input = trim(fgets(STDIN));
            system('stty echo');
            echo PHP_EOL;
        } 
        return $input;
    }


Als ik descriptorspec[0] verander in een pipe (was eerst) dan komt er een prompt waar ik kan typen wat ik wil, maar dan blijft ie hangen bij invoer (maar hij geeft niet de tekst weer).

Als ik descriptorspec[0] naar een file doe, dan komt ie bij terminal.readline maar de echo blijft uit. (In mijn voorbeeld heb ik 3 readlines, deze invullen en de code gaat verder en toont daarna pas de bijbehorende tekst.

Oftewel als ik het via "execute" doe dan gaat het niet goed, voer ik het in de terminal direct uit, gaat het wel goed.

Wat gaat er niet goed:

er komt 3x een blanke cursors (zonder text die er wel bij hoort)
Daarna komt de tekst

Bash:
1
2
3
4
5
6
7
y
y
n
Setup r3m-io/priya:
This will setup r3m-io/priya. Are you sure you want to continue (y/n):
This will setup r3m-io/priya. Are you sure you want to continue (y/n):
This will setup r3m-io/priya. Are you sure you want to continue (y/n):


ik heb ook exec, shell_exec geprobeert met hetzelfde resultaat.
Al wat gelezen over blocking / non / blocking maar kom maar niet verder.

...

Relevante software en hardware die ik gebruik

php 7.4
debian 11
...


Wat ik al gevonden of geprobeerd heb

https://stackoverflow.com...pipe-when-using-proc-open


toch nog verder gekomen:

- The answer is surprisingly simple: leave $descriptorspec empty.

dan is de vraag, waarom gaat het wel goed als ik $descriptorspec leeglaat en gaat het niet goed als ik ze beschrijf...
...

Alle reacties


  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Dat is best ingewikkeld. Ik moest er ook aardig mee stoeien toen ik gpg aan moest roepen via PHP en gpg om wachtwoord ging vragen.

Misschien heb je wat aan mijn code hoe ik dat heb opgelost.
https://github.com/the-dj...es/snappymail/pgp/gpg.php

Maak je niet druk, dat doet de compressor maar


Acties:
  • +1 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Misschien kun je Symfony Process proberen, die lost de communicatie op met het OS zodat jij je kunt focussen op de specifieke tool.


https://symfony.com/doc/current/components/process.html

Acties:
  • 0 Henk 'm!

Anoniem: 80910

Topicstarter
Ja, ik had al in de symfony source code gekeken en die gebruiken alleen descriptor 1 en 2, 0: stdin laten ze default. Met mijn test ging dat ook fout: je start een script en dat script start weer een ander script met een prompt.

Ik ga options gebruiken.
-prompt voor prompt scripts,
-file, wordt beschikbaar en
-stream die de machine state van variabelen doorgeeft aan het volgende script.
Kan ik met -stream ook inbakken dat een process gestart is met een bepaald script. Aan de hand van variabelen. Met -stream kun je dan een stappenplan bijvoorbeeld 30 subprocessen uitvoeren zonder prompt.

Prompt wordt denk ik de default.

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Anoniem: 80910 schreef op zaterdag 18 februari 2023 @ 23:32:
Ja, ik had al in de symfony source code gekeken en die gebruiken alleen descriptor 1 en 2, 0: stdin laten ze default. Met mijn test ging dat ook fout: je start een script en dat script start weer een ander script met een prompt.
Waarom gebruik je de genoemde library niet gewoon ipv het wiel opnieuw uitvinden?

Acties:
  • 0 Henk 'm!

Anoniem: 80910

Topicstarter
Ja, die vraag is hetzelfde als waarom zijn er merken en smaken. Voorkeur en begrip. Ik denk dat het wat meer tijd kost om dat goed te implementeren en waarschijnlijk moet ik daar dingen voor wegschrijven in een config. Met zulke packages ben ik net begonnen. Ik denk dat het bij symfony ook fout gaat, maar dat weet ik niet zeker. Ik wil die package in de toekomst wellicht kunnen toevoegen aan mijn framework, die dingen in mijn ogen net iets platter, simpeler oplost dan symfony. Daarnaast is het al bruikbaar en mijn prompt werkt. Ik vind het alleen raar dat als je bijvoorbeeld de ouput als een stream behandeld, de input fout gaat. Dat kan ook aan mijn php versie liggen of aan het feit dat het om een proces in een proces gaat met prompt mogelijkheid. Mijn tests wijzen uit dat je de constantes stdin, stdout moet gebruiken voor dit probleem. Error mag wel een stream zijn.

Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Anoniem: 80910 schreef op zondag 19 februari 2023 @ 22:16:
Ik denk dat het bij symfony ook fout gaat, maar dat weet ik niet zeker.
Nou, probeer het eerst eens misschien? :)
Pagina: 1