SSH2_Exec takes way too long to execute commands. - PHP - php

I am trying to execute a command on my VPS using SSH2, but for some reason, the first command always takes around 10 seconds to execute. The wierd part is that the rest of the commands, after the first one, get executed instantly after those 10 seconds.
Did I do something wrong? Or is it normal? If so, how can I fix this.
class SSH
{
public $connection = null;
public $results = "";
public $errors = "";
public function __construct($host, $port)
{
$this->connection = ssh2_connect($host, $port);
}
public function login($username, $password)
{
if(!$this->connection)
return false;
if(!ssh2_auth_password($this->connection, $username, $password))
return false;
return true;
}
public function execute($command)
{
if(!$this->connection)
return false;
error_log("[debug] starting command.");
$response = ssh2_exec($this->connection, $command);
if(!$response)
return false;
error_log("[debug] command executed.");
fclose($response);
return true;
}
public function disconnect()
{
if(!$this->connection)
return false;
return ssh2_disconnect($this->connection);
}
}
I've logged the messages and as you can see below, it takes ~10 seconds to execute and the rest are instant.
[23-Sep-2019 17:25:42 Europe/Helsinki] [debug] starting command. (command 1)
[23-Sep-2019 17:25:51 Europe/Helsinki] [debug] command executed.
[23-Sep-2019 17:25:51 Europe/Helsinki] [debug] starting command. (command 2)
[23-Sep-2019 17:25:51 Europe/Helsinki] [debug] command executed.

Related

Php - socket_read with pthreads

I know socket and thread is horrible in php... I'm just trying to connect my php file with socket to my server.
The problem is I got nothing from socket_read (no datas no error just returning an empty string) and I think pthread kill automatically the socket.
For now I don't need thread but I need to keep it to use it later.
My code:
<?php
class test extends Threaded
{
/*
*/
public function __construct($ip, $port, $debug = false)
{
$this->debug = $debug;
$this->ip = $ip;
$this->port = $port;
}
/*
*/
public function __destruct()
{
socket_close($this->connect);
}
/*
*/
public function start()
{
if (!($this->connect = socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
throw new Exception('SOCKET_CREATE');
}
if (!socket_set_option($this->connect, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 5, 'usec' => 0))) {
throw new Exception('SOCKET_SET_OPTION');
}
if (!socket_connect($this->connect, $this->ip, $this->port)) {
throw new Exception('SOCKET_CONNECT');
}
$getMsg = socket_read($this->connect, 255);
echo $getMsg;
}
}
Do you know how it can works?
EDIT: I tried again today and my script works, I don't understand sometime it works sometime not ....
EDIT2: I copied my server file script to an other server with much much more traffic and it works ! So why it works on the server 2 and not on server 1 ?

fgets reading very slow compared to socket_recv

I've been having issues with reading data from a Python socket server. I've tried several methods and have been searching for a solution for months.
The response I am trying to get from the Python socket server is different every time. It can be 40 characters the first time and over 10k characters the next.
I've tried to use socket_recv() and fgets() and so far fgets works the best for what I need, as socket_recv doesn't get the whole response when fgets does. There's just one problem. It's so much slower compared to socket_recv, and doesn't always get the response.
The problem I am having with fgets is that it takes 2.02 seconds to get the response on a local connection, no matter how big or small it is.
I need it to go down, but I can't for the life of me figure out how to fix it..
Connecting to the Python socket server only takes 22ms, so I don't get why it'd take long at all to get the whole reponse.
Oh and if it helps, the response is a JSON string.
Here's the code I use:
/*
* Recieve
*/
public function recv() {
if (!$this->connected()) {
$this->_errorStr = 'Recieve timeout';
$this->_error = true;
return false;
}
$buf = '';
while ($line = fgets($this->_socket)) {
$buf .= $line;
}
return json_decode($buf);
}
And if you need the whole class:
class Sockets {
/*
* Variables
*/
private $_id,
$_name,
$_ip,
$_port,
$_socket,
$_socketTimeout = 1,
$_triedConnect = false,
$_errorStr = '',
$_error = false;
/*
* Construct class
*/
public function __construct($ip, $port) {
$this->_ip = $ip;
$this->_port = $port;
$this->_socket = false;
}
/*
* Send command
*/
public function command($cmd, $json = true) {
if ($json) {
$cmd = json_encode($cmd);
}
if (!$this->send($cmd)) {
return $this->_errorStr;
}
$r = $this->recv();
if (!$r) {
return $this->_errorStr;
}
return $r;
}
/*
* Connect to server
*/
public function connect() {
$this->_error = false;
if ($this->_triedConnect) {
$this->_errorStr = 'Failed to connect.';
$this->_error = true;
return false;
}
$this->_triedConnect = true;
$this->_errorStr = '';
$errno = 0;
$errstr = '';
$this->_socket = #pfsockopen($this->_ip, $this->_port, $errno, $errstr, $this->_socketTimeout);
if (!$this->_socket) {
$this->_errorStr = sprintf('Can\'t connect to server.. (%errno: %errstr)', $errno, $errstr);
$this->_error = true;
$this->_socket = false;
return false;
}
stream_set_timeout($this->_socket, $this->_socketTimeout);
// Clear stream
while ($this->dataReady()) {
if (!fgets($this->_socket)) {
break;
}
}
if (!$this->connected()) {
$this->_errorStr = 'Lost connection to server!';
$this->_error = true;
$this->_socket = false;
return $this->_errorStr;
}
return true;
}
/*
* Authentication
*/
public function auth() {
}
/*
* Connected
*/
public function connected() {
return $this->_socket !== false;
}
/*
* Data ready
*/
public function dataReady() {
if (!$this->connected()) {
return false;
}
return #stream_select($r = array($this->_socket), $w = null, $x = null, 0) > 0;
}
/*
* Send data
*/
public function send($data) {
if (!$this->connected()) {
$this->_errorStr = 'Not connected!';
$this->_error = true;
return false;
}
if (#fwrite($this->_socket, $data) === false) {
$this->_errorStr = 'Failed to send command!';
$this->_error = true;
return false;
}
return true;
}
/*
* Recieve
*/
public function recv() {
if (!$this->connected()) {
$this->_errorStr = 'Recieve timeout';
$this->_error = true;
return false;
}
$buf = '';
while ($line = fgets($this->_socket)) {
$buf .= $line;
}
return json_decode($buf);
}
/*
* Disconnect
*/
public function disconnect() {
if (!$this->connected()) {
return;
}
fclose($this->_socket);
$this->_socket = false;
$this->_triedConnect = false;
}
}
Any help is really appreciated!
EDIT
The machine I am using is running Windows 8.1 Pro, with Media Center.
I am using Python 2.7.9 for the server with the following dependencies installed:
psutil <- https://pypi.python.org/pypi/psutil
colorama <- https://pypi.python.org/pypi/colorama
pycrypto <- http://www.voidspace.org.uk/python/modules.shtml#pycrypto
It shouldn't matter what type of TCP socket server at all. Just a basic one should work just to test this. Even without the dependencies. Something like this works.
For PHP I am using Wamp and PHP 5.5.12 with the following modules enabled:
php_bz2
php_com_dotnet
php_curl
php_exif
php_fileinfo
php_gd2
php_gettext
php_gmp
php_imap
php_intl
php_ldap
php_mbstring
php_mysql
php_mysqli
php_openssl
php_pdo_mysql
php_pdo_sqlite
php_shmop
php_soap
php_sockets
php_sqlite3
php_xmlrpc
php_xsl
Some, if not all of those, are enabled on default.
To test the Sockets class, all you need is to is something like this:
// Import class file
require_once 'Sockets.php';
$socket = new Sockets('127.0.0.1', 21); // Change the port accordingly
// Connect to socket server
$socket->connect();
// Now in my case, the socket server responds to JSON strings, and nothing else.
// So I am going to show you show I send a command.
$command = array(
'key' => 'encrypted key', // This key is to do some validation on the server-side
'command' => 'command' // This is the command to be issued.
);
// Send command to socket server and dump the response
var_dump($socket->command($command));
// To send a plainstring command use this instead
var_dump($socket->command('command here', false));
After quite a lot of debugging and further searching the interwebs and not finding anything, I finally found an answer to my issue.
The issue was with the Python socket server. After sending a command to the socket server, it sends a response back with the requested data. The socket server should then close the connection. And this is where the issue was. It was sending the response, but not closing the connection, so all I had to do was close the connection after every command. The response time went from 2.02 seconds down to 20ms, which is what I wanted.

PHP - MongoClient connections stacking up, not closing

I've got a class that is pulling and aggregating data from a Mongo DB. This is all working fine...I have multiple queries being run for a connection under the same connection (in the same class). However, every time I refresh the page, a new connection is opened...I can see this in my mongod output:
[initandlisten] connection accepted from 127.0.0.1:46770 #12 (6 connections now open)
I see this count up and up with every page refresh. This should be fine, I think; however, the connections never seem to close.
After a while, the connections / locks take up too much memory in Mongo, and I can no longer run the queries.
This dev environment is on a 32-bit version of Mongo, so I don't know if this is only happening because of that. (Our prod env is 64-bit, and I cannot change the dev env right now.)
My question is: Should I be closing the connection after all the queries have been made for a particular user? How should I be handling the connection pool?
The service class:
class MongoService{
protected $mongoServer;
public function setSpokenlayerMongoServer($mongoServer)
{ $this->mongoServer = $mongoServer; }
protected $mongoUser;
public function setSpokenlayerMongoUser($mongoUser)
{ $this->mongoUser = $mongoUser; }
protected $mongoPassword;
public function setSpokenlayerMongoPassword($mongoPassword)
{ $this->mongoPassword = $mongoPassword; }
protected $conn;
public function setServiceConnection($conn)
{ $this->conn = $conn; }
public function connect(){
try {
$this->conn = $this->getMongoClient();
} catch(Exception $e) {
/* Can't connect to MongoDB! */
// logException($e);
die("Can't do anything :(");
}
}
public function getDatabase($name){
if(!isset($this->conn)){
$this->connect();
}
return $this->conn->$name;
}
protected function getMongoClient($retry = 3) {
$connectString= "mongodb://".$this->mongoUser.":".$this->mongoPassword."#". $this->mongoServer."";
try {
return new MongoClient($connectString);
} catch(Exception $e) {
/* Log the exception so we can look into why mongod failed later */
// logException($e);
}
if ($retry > 0) {
return $this->getMongoClient(--$retry);
}
throw new Exception("I've tried several times getting MongoClient.. Is mongod really running?");
}
}
And in the service class where the queries are:
protected function collection(){
if(!isset($this->collection)){
$this->collection = $this->db()->selectCollection($this->collectionName);
}
return $this->collection;
}
And then a query is done like so:
$results = $this->collection()->aggregate($ops);
Is this correct behavior?
Known issue if you're using Azure IaaS, possible issue on other platforms.
One option would be to change the Mongo configuration:
MongoDefaults.MaxConnectionIdleTime = TimeSpan.FromMinutes(5);
This would kill all idle connections after 5 minutes.

PHp fsockopen() communicating via Telnet

I'm looking for a guide on how to use fsockopen() to communicate with a telnet system.... I'm connected just fine, but the command is failing to send. I've seen some documentation fwrite() that shows people sending some headers.
Currently the command I'm running against the telnet server is version via $class->send("version");. Do I need to send headers or anything along with this for the telnet server to pick up the command, or can I just send that?
/**
* Connect to the GMC telnet system
*/
public function connect () {
$this->connection = fsockopen($this->socket['host'], $this->socket['port'], $errorNumber, $errorMessage, 30);
if (!$this->connection) {
$this->error = 'Unable to connect to GMC: '.$errorMessage.' ('.$errorNumber.')';
return false;
}
stream_set_timeout($this->connection, $this->commandTimeout);
return true;
}
/**
* Send a command to GMC
*/
public function send ($command) {
//write to socket
if (fwrite($this->connection, $command) === false) {
$this->error = 'Unable to write to socket';
return false;
}
sleep(1);
//read socket
if (($response = fgets($this->connection)) === false) {
$this->error = 'Unable to write to socket';
return false;
}
return $response;
}
/**
* Disconnects from the GMC telnet system
*/
public function disconnect () {
return fclose($this->connection);
}
Apparently all I needed to do was be sure I included a \n at the end of my command!!

PHP mysqli segmentation fault

im trying to extend the mysqli class in php in order to create a wrapper class. I would like this class to manage multiple connections.. I am currently at a very early stage and have hit a problem:
Auth Connected no: 1
1045:Access denied for user 'rootty'#'localhost' (using password: YES)
Segmentation fault
It seems when the second connection has an error a segmentation fault is created however connection one errors correctly..
<?php
class mysqli_ls extends mysqli
{
private $link = array();
private $link_no = 0;
/* ************************************************************ */
public function __construct()
{
}
/* ************************************************************ */
public function open($host='', $user='', $pass='', $port='3306', $database='')
{
if ( empty($host) || empty($user) || empty($pass) || empty($database) )
{
$this->error[] = "Missing required connection variables";
return false;
}
$this->link_no++;
#$this->link[ $linkno ] = $this->connect($host, $user, $pass, $database, $port);
if ($this->connect_errno)
{
$this->error[] = $this->connect_errno .':'. $this->connect_error;
return false;
}
return $this->link_no;
}
######Test script
#!/usr/bin/php
<?php
require_once('mysqli.class.php');
$_mysqli = new mysqli_ls;
$_auth = $_mysqli->open('localhost','root','xx','3306','auth');
if ($_auth === false) print $_mysqli->get_last_error() ."\n";
else print 'Auth Connected no: '. $_auth ."\n";
$_trak = $_mysqli->open('localhost','root','sxx','3306','wlr_tracker');
if ($_trak === false) print $_mysqli->get_last_error() ."\n";
else print 'Trak Connected no: '. $_trak ."\n";
I would report this to the PHP/mysqli devs. A scripting language segfaulting is most likely an internal bug you cannot fix - while it might be possible to create a workaround the proper way is to get it fixed in the C code.

Categories