Ankündigung

Einklappen
Keine Ankündigung bisher.

Interaktive session mit proc_open funktioniert nicht?

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Interaktive session mit proc_open funktioniert nicht?

    Hallo zusammen,

    ein PHP-Skript auf meinem Ubuntu Webserver soll interaktiv mit einer Binary (ein Computeralgebra-Programm namens Reduce) kommunizieren. Ich habe bis jetzt folgenden Code:

    Code:
    $descriptorspec = array(
    	0 => array("pipe","r"),
    	1 => array("pipe","w"),
    	2 => array("file","./error.log","a")
    ) ;
    
    // working directory
    $cwd = './' ;
    
    // open reduce
    $process = proc_open('./reduce/reduce', $descriptorspec, $pipes, $cwd) ;
    
    if (is_resource($process)) {
    
    	fwrite($pipes[0], 'load excalc$\n');
    	fclose($pipes[0]);
    
    	echo stream_get_contents($pipes[1]) ;
    
    	fclose($pipes[1]);
    	proc_close($process);
    
    }
    Das funktioniert auch so weit. Das Problem: Bevor ich STDOUT mittels stream_get_contents auslese muss ich STDIN schliessen, und damit beende ich ja unfreiwillig die Session da ich meinen STDIN verloren habe.

    Was also tun?

    Gruss
    Jens

  • #2
    Code:
    'load excalc$\n'
    Das \n wird nicht als Newline interpretiert sondern einfach nur als \n (2 normale Zeichen).
    [QUOTE=nikosch]Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.[/QUOTE]

    Kommentar


    • #3
      Okay, stimmt. Abert ist ja nicht Ursache des Problems. Ich muss die Pipe Nummer 0 (also den STDIN) schliessen, und erst dann kann ich mit stream_get_contents den Inhalt auslesen... Warum ist das so? Ich will den STDIN ja offen halten fuer spaetere Eingaben.

      Kommentar


      • #4
        Das liegt vermutlich daran, dass stream_get_contents solange wartet, bis der (Out)Stream geschlossen wurde bzw. das Streamende-Singnal übertragen wurde. Und das passiert nunmal erst, wenn das Programm beendet wurde.

        Versuch es mit non-blocking Mode http://php.net/manual/de/function.st...t-blocking.php in verbindung mit fgets oder fread
        [QUOTE=nikosch]Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.[/QUOTE]

        Kommentar


        • #5
          Ich denke auch, dass es was damit zu tun hat. Ich probiere es und melde mich hier.

          Kommentar


          • #6
            Also jetzt haengt er nicht mehr. Aber ich bekomme logischerweise keinen Input.
            Code:
            if (is_resource($process)) {
            
            	stream_set_blocking($pipes[1], 0);
            
            	fwrite($pipes[0], 'load excalc; operator x; x(0) := t; x(1) := r;');		
            	sleep(2);
            	$lines = array();				
            	while($line = fgets($pipes[1], 4096)) {
            		$lines[] = trim($line);
            	}
            	echo "output:<br>";
            	foreach ($lines as $line) {
            		echo $line . "<br>";
            	}
            	
            	
            	fwrite($pipes[0], 'coframe o(t) = sqrt(1-2m/r) * d t, o(r) = 1/sqrt(1-2m/r) * d r with metric g = -o(t)*o(t) + o(r)*o(r); displayframe;');
            	sleep(2);
            	$lines = array();
            	while($line = fgets($pipes[1], 4096)) {
            		$lines[] = trim($line);
            	}
            	echo "output:<br>";
            	foreach ($lines as $line) {
            		echo $line . "<br>";
            	}
            					
            
            	// close pipes & close process
            	fclose($pipes[0]);
            	fclose($pipes[1]);
            	fclose($pipes[2]);
            	proc_close($process);
            
            }
            Also habe ich mal als groben Test ein sleep eingebaut. Das erste sleep(1) fuehrt dazu, dass die ersten Ausgaben sichtbar werden. Das heisst mein Output ist im Moment
            Code:
            output: Reduce (Free CSL version), 14-Apr-11 ...
            output:
            Aber: der zweite Output laesst auf sich warten. Warum?

            Kommentar


            • #7
              Ich kenne das Programm nicht, weiß also nicht was es erwartet und ausgibt, aber bist du dir sicher, dass du kein Break(Newline) nach der Eingabe senden musst?
              [QUOTE=nikosch]Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.[/QUOTE]

              Kommentar


              • #8
                Oh mann, das ware's noch. Wie mache ich das? \n\r ? Ich bin damit immer unsicher auf verschiedenen Systemen.

                Kommentar


                • #9
                  \n für Unix
                  \r\n für Windows
                  \r für Mac

                  Wobei Mac in den neueren Versionen auch auf \n umgestiegen ist.
                  [QUOTE=nikosch]Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.[/QUOTE]

                  Kommentar


                  • #10
                    Ah OK. Aber das ist es nicht, ich habe vergessen dass die erste Ausgabe vom Launch './reduce/reduce' stammt, das ist die Default-Ausgabe des Programms. Und wenn ich die ganzen Befehle mit fwrite in $pipes[0] reinschreibe, dann schliesse, und dann stream_get_contents abfrage, erhalte ich alle Ausgaben korrekt... Hier mein aktueller Code, der jetzt gar nichts mehr ausgibt (ausser der Launch-Bestaetigung des Programms):
                    Code:
                    if (is_resource($process)) {
                    
                    	stream_set_blocking($pipes[1], 0);
                    
                    	sleep(1);
                    	$lines = array();				
                    	while($line = fgets($pipes[1], 4096)) {
                    		$lines[] = trim($line);
                    	}
                    	echo "output 1:<br>";
                    	foreach ($lines as $line) {
                    		echo $line . "<br>";
                    	}
                    
                    	fwrite($pipes[0], 'load excalc; operator x; x(0) := t; x(1) := r;\r\n');		
                    	$lines = array();				
                    	while($line = fgets($pipes[1], 4096)) {
                    		$lines[] = trim($line);
                    	}
                    	echo "output 2:<br>";
                    	foreach ($lines as $line) {
                    		echo $line . "<br>";
                    	}
                    	
                    	fwrite($pipes[0], 'coframe o(t) = sqrt(1-2m/r) * d t, o(r) = 1/sqrt(1-2m/r) * d r with metric g = -o(t)*o(t) + o(r)*o(r); displayframe;\r\n');
                    	$lines = array();
                    	while($line = fgets($pipes[1], 4096)) {
                    		$lines[] = trim($line);
                    	}
                    	echo "output 3:<br>";
                    	foreach ($lines as $line) {
                    		echo $line . "<br>";
                    	}				
                    
                    	// close pipes & close process
                    	fclose($pipes[0]);
                    	fclose($pipes[1]);
                    	fclose($pipes[2]);
                    	proc_close($process);
                    
                    }
                    Ausgabe:
                    Code:
                    output 1:
                    Reduce (Free CSL version), 14-Apr-11 ...
                    
                    1:
                    output 2:
                    output 3:

                    Kommentar


                    • #11
                      Das \r\n zwischen den Singlequotes wird immernoch nicht als CRLF Interpretiert sondern immernoch als 4 normale Zeichen...
                      [QUOTE=nikosch]Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.[/QUOTE]

                      Kommentar


                      • #12
                        Stimmt, sorry. Aber hat keinen Einfluss auf das Ergebnis. Neuer Code, selbe Ausgabe wie unten.
                        Code:
                        if (is_resource($process)) {
                        
                        	stream_set_blocking($pipes[1], 0);
                        
                        	sleep(1);
                        	$lines = array();				
                        	while($line = fgets($pipes[1], 4096)) {
                        		$lines[] = trim($line);
                        	}
                        	echo "output 1:<br>";
                        	foreach ($lines as $line) {
                        		echo $line . "<br>";
                        	}
                        
                        	fwrite($pipes[0], 'load excalc; operator x; x(0) := t; x(1) := r;' . PHP_EOL);		
                        	$lines = array();				
                        	while($line = fgets($pipes[1], 4096)) {
                        		$lines[] = trim($line);
                        	}
                        	echo "output 2:<br>";
                        	foreach ($lines as $line) {
                        		echo $line . "<br>";
                        	}
                        	
                        	fwrite($pipes[0], 'coframe o(t) = sqrt(1-2m/r) * d t, o(r) = 1/sqrt(1-2m/r) * d r with metric g = -o(t)*o(t) + o(r)*o(r); displayframe;' . PHP_EOL);
                        	$lines = array();
                        	while($line = fgets($pipes[1], 4096)) {
                        		$lines[] = trim($line);
                        	}
                        	echo "output 3:<br>";
                        	foreach ($lines as $line) {
                        		echo $line . "<br>";
                        	}				
                        
                        	// close pipes & close process
                        	fclose($pipes[0]);
                        	fclose($pipes[1]);
                        	fclose($pipes[2]);
                        	proc_close($process);
                        
                        }
                        Ausgabe
                        Code:
                        output 1:
                        Reduce (Free CSL version), 14-Apr-11 ...
                        
                        1:
                        output 2:
                        output 3:

                        Kommentar


                        • #13
                          Habe was gefunden was gut laeuft:
                          Code:
                          define('TIMEOUT_IN_MS', '100');
                          define('TIMEOUT_STEPS', '100');
                          
                          function getOutput ($pipes) {
                          	$result = "";
                          	$stage = 0;
                          	$buffer = 0;
                          	do {
                          		$char = fgets($pipes[1], 4096);
                          		if ($char != null) {
                          			$buffer = 0;
                          			$stage = 1;
                          			$result .= $char;
                          		} else if ($stage == "1") {
                          			usleep(TIMEOUT_IN_MS/TIMEOUT_STEPS);
                          			$buffer++;
                          			if ($buffer > TIMEOUT_STEPS) {
                          				$stage++;
                          			}
                          		}
                          	} while ($stage < 2);
                          	return $result;
                          }
                          
                          $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w") ) ;
                          
                          // define current working directory where files would be stored
                          $cwd = './' ;
                          
                          // open reduce
                          $process = proc_open('./reduce/reduce', $descriptorspec, $pipes, $cwd);
                          
                          if (is_resource($process)) {
                          
                          	stream_set_blocking($pipes[1], 0);
                          	
                          	echo "startup output:<br><pre>" . getOutput($pipes) . "</pre>";
                          
                          	fwrite($pipes[0], 'on output; load excalc; operator x; x(0) := t; x(1) := r;' . PHP_EOL);
                          	echo "output 1:<br><pre>" . getOutput($pipes) . "</pre>";
                          	
                          	fwrite($pipes[0], 'coframe o(t) = sqrt(1-2m/r) * d t, o(r) = 1/sqrt(1-2m/r) * d r with metric g = -o(t)*o(t) + o(r)*o(r); displayframe;' . PHP_EOL);
                          	echo "output 2:<br><pre>" . getOutput($pipes) . "</pre>";
                          
                          	// close pipes & close process
                          	fclose($pipes[0]);
                          	fclose($pipes[1]);
                          	fclose($pipes[2]);
                          	proc_close($process);
                          
                          }

                          Kommentar

                          Lädt...
                          X