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).
    Zitat von nikosch
    Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.

    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
        Zitat von nikosch
        Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.

        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?
              Zitat von nikosch
              Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.

              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.
                  Zitat von nikosch
                  Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.

                  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...
                      Zitat von nikosch
                      Macht doch alle was Ihr wollt mit Eurem Billigscheiß. Von mir aus sollen alle Eure Server abrauchen.

                      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