J'ai téléchargé un émulateur de terminal open-source de github et je l'ai modifié un peu. La classe pour l'exécution d'un processus ressemble à ceci:PHP Script se bloque lors du passage d'un paramètre à traiter
<?php
class CProcess {
const PROC_OK = true;
const PROC_FAILED = false;
private static $instance = null;
public static function factory() {
if (!isset(self::$instance)) {
self::$instance = new CProcess();
}
return self::$instance;
}
private $pipes;
private $process;
private $stdinref;
private $stdoutref;
private $stderref;
private function __construct() {
}
public function __destruct() {
return $this->close();
}
public function open($command) {
$spec = array(
array("pty"), // STDIN
array("pty"), // STDOUT
array("pty") // STDERR
);
if (!$this->process = proc_open($command, $spec, $this->pipes)) {
return self::PROC_FAILED;
}
$this->stdinref = &$this->pipes[0];
$this->stdoutref = &$this->pipes[1];
$this->stderref = &$this->pipes[2];
$this->setBlocking(0);
return self::PROC_OK;
}
public function isResource() {
return is_resource($this->process);
}
public function setBlocking($blocking = 1) {
return stream_set_blocking($this->stdoutref, $blocking);
}
public function getStatus() {
return proc_get_status($this->process);
}
public function get() {
$out = stream_get_contents($this->stdoutref);
return $out;
}
public function put($data) {
fwrite($this->stdinref, $data . "\n");
sleep(1);
fflush($this->stdinref);
}
public function close() {
if (is_resource($this->process)) {
fclose($this->stdinref);
fclose($this->stdoutref);
fclose($this->stderref);
return proc_close($this->process);
}
}
public function metaData() {
return stream_get_meta_data($this->stdoutref);
}
}
Maintenant, je veux authentifier une paire login/mot de passe en utilisant la méthode suivante:
public static function autenticate($login, $password) {
if (true === DEBUG_MODE) {
error_log("authenticate(): login={$login} password={$password}",0);
}
error_log("test");
self::$username = $login;
$process = CProcess::factory();
$cmd = "su " . escapeshellarg($login);
if (true === DEBUG_MODE) {
error_log("authenticate(): cmd={$cmd}", 0);
}
$rc = $process->open($cmd);
usleep(100000); // 500000
if ($rc === CProcess::PROC_FAILED) {
if (true === DEBUG_MODE) {
error_log("authenticate(): process_open() returns {$rc}", 0);
}
return false;
}
if (true === DEBUG_MODE) {
error_log("authenticate(): invoking process->put() with param={$password}");
}
$process->put($password);
if (true === DEBUG_MODE) {
error_log("authenticate(): process->put() returned its value");
}
usleep(100000);
return (bool) !$process->close();
}
Le problème est que le script se bloque lorsque entrer dans $process->put($password);
. Mon navigateur affiche simplement 'Waiting for localhost' et ça dure pour toujours. Dans la méthode put();
de la classe CProcess
j'ai également essayé PHP_EOL
au lieu de \n
mais le résultat était le même. Quel est le problème avec ce code?
Êtes-vous sûr que le VARIABLES 'spec' de $ est corect dans votre fonction ouverte? Le document PHP de [proc_open] (http://php.net/manual/en/function.proc-open.php) indique que le second élément est soit r pour passer l'extrémité de lecture du tube au processus, soit pour passer la fin d'écriture »et vous n'avez pas du tout utilisé un second élément, je ne pense pas que ce soit optionnel ici! – xander
Oui, j'ai présenté le tableau '$ spec' tel qu'il est écrit dans mes notes de cours. –