PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [PHP] Problem listen-socket & exec()



sparky
25.01.2004, 22:08
Servus, also folgendes Problem:

Die Klasse macht einen ListenServer auf einem bestimmten Port (55555) und horcht auf Verbindungen. Die Commands die ankommen haben dann folgendes Format: array('command' => 'cm_xxx', 'arg1' => 'blubb' ...)

Das ganze rennt dann natürlich in der Console:




class ListenServer extends BaseServer
{
var $readEndCharacter = "\r\n\r\n";


function onReceiveData( $clientId, $data )
{
$request = unserialize( $data );
if( preg_match("/^cm_/i", $request['command']) )
{

switch($request['command']) {
case 'cm_system': $response = $this->Run($response, $request['arg1']);
break;
case 'cm_writefile': $response = $this->writeFile($response, $request['arg1'], $request['arg2']);
break;
case 'cm_getfile': $response = $this->getFile($response, $request['arg1']);
break;
default:
$response .= "no action found";
$this->sendDebugMessage("Server::Receive(): no matching action");
}
}

else
{
$response = "error\r\n"
}

$this->sendDebugMessage("Server::Send(): $response");
$this->sendData( $clientId, $response, false);
$this->closeConnection( $clientId );
}

function Run($res, $cmd) {
$this->sendDebugMessage("Server::Run(): $cmd");
if(!escapeshellcmd($cmd)) return false;
exec(escapeshellcmd($cmd), $o, $r);
$this->sendDebugMessage("Server::Run(): output: $o | res: $r | ret: ".serialize(array($o, $r)));
return $res . serialize(array($o, $r, 'return' => 'command executed')) . "\r\n\r\n";
}

function GetFile($res, $file) {
$str = file($file);
$this->sendDebugMessage("Server::getFile(): $file | str: " . serialize($str));
return $res . serialize($str) . "\r\n\r\n";
}

function WriteFile($res, $file, $str) {
$this->sendDebugMessage("Server::writeFile(): file: $file |str: $str");
if(is_link($file)) {
$this->sendDebugMessage("Server::writeFile(): deleting symlink: $file");
$this->Run('rm -f ' . $file);
$this->Run('touch ' . $file);
}
$fp = fopen($file, 'w');
foreach($str as $value) {
fwrite($fp, trim($value) . "\n");
}
fclose($fp);
return $res . "\r\n\r\n";
}
}




in meinem PHP Script (nicht in der Console, sondern normal Webserver) kommunisizere ich dann mit diesem Code: ($data = serialisiertes Array)



function DaemonSend($data) {
$socket = socket_create (AF_INET, SOCK_STREAM, 0);
$result = socket_connect ($socket, $ip, 55555);
$in = $data . "\r\n\r\n";
$out = '';
socket_write ($socket, $in, strlen ($in));

while ($res = socket_read($socket, 2048)) {
$out .= $res;
}
socket_close ($socket);
return unserialize($out);
}




so jetzt das Problem:
es geht alles reibungslos, nur wenn ich auf dem ListenServer die Methode Run() verwende und ein System Commando ausführen will, dann läuft mein PHP-Script auf dem Webserver in ner Endlosschleife. Bei allen anderen Methoden geht alles. Das System Commando wird sogar im Hintergrund gestartet & die Ausgaben umgelenkt (über ein Shellscript) so dass das Shellscript nur die PID von dem Ausgeführten Befehl zurückgibt. Wenn ich das gestartete Commando kille, dann lädt das Webserver-PHP File fertig.

An was kann das liegen ? Wenn ich dieselbe Run() Funktion local auf dem seelben Rechner ausführe wie mein Webserver-Script, dann geht alles optimal.

EDIT: ich habs auch mit anderen Fkt anstatt exec() versucht, aber mit allen dasselbe Problem

thorus
25.01.2004, 23:47
Hmm, nur noch zum Nachtrag andere Fkts zum Ausführen:
http://de3.php.net/manual/en/function.passthru.php
http://de3.php.net/manual/en/function.proc-open.php (usw.)
http://de3.php.net/manual/en/function.shell-exec.php
http://de3.php.net/manual/en/function.system.php

Eins müsste doch normal gehen.. erwartet dein Programm eventuell Input?

Schau dir auch mal die Kommentare zu den Befehlen an, sind manchmal nützliche Sachen dabei ;)

sparky
26.01.2004, 15:04
hmpf keine Chance, ich hab ALLE versucht nochmal, das tolle ist ja, der Listen-Socket beendet die Verbindung:

Debug:


2004-01-26 15:44:49 Server::Run(): output: Array | res: Array | ret: a:2:{i:0;a:1:{i:0;a:1:{i:0;s:5:"15987";}}i:1;a:1:{i:0;i:0;}}
2004-01-26 15:44:49 Server::Send(): a:3:{i:0;a:1:{i:0;a:1:{i:0;s:5:"15987";}}i:1;a:1:{i:0;i:0;}s:6:"return";s:16:"command executed";}
2004-01-26 15:44:49 Closed connection ( 0 ) from 192.168.0.161 on port 32812


aber das empfangende Script scheint sich bei socket_read() aufzuhängen :(

Steve
27.01.2004, 17:23
hi,

du hast eigentlich ein Problem dabei warum sich dein Script so verhält und sich der Client beendet: Bei einem exec wird normalerweise (ich glaub bei PHP nicht) der Prozess durch das gestartete Programm ersetzt. Bei PHP gibt IMHO exec nur den Output zurück. Aber er blockiert, da er so lange wartet bis der Prozess fertig ist, deshalb denkt der Client IMHO auch, dass die Connection beendet wurde und er schließt sie deshalb auch.

So nun ein Lösungsvorschlag: häng ein & an deinen Befehl an.

Steve

PS keine Ahnung ob stimmt. :)

sparky
27.01.2004, 17:37
EDIT:

also es liegt wohl an meinem Shellscript, denn ein "ls -l" oder ein shellscript mit einem einfachen "echo test" geht wunderbar.
das script:



#!/bin/bash
#export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
cd $(dirname "$1")
SVBIN=$(basename "$1")

for param ; do
if [ "$param" != "$1" ] ; then
SVARGS="$SVARGS $param"
fi
done

./${SVBIN}${SVARGS} 2>/dev/null 1>/dev/null &
curr_pid=$!
echo "$curr_pid"
exit 0


negativ.
und wie gesagt, wenn ich denselben Code lokal aufrufe geht ja alles ...