Php does not block SSH client instances

Source: Internet
Author: User
Tags public key authentication failed

In my previous work, I had to deal with foreign servers. The latency and packet loss problems were sometimes very serious. It was intolerable to enter an SQL statement. Google searched once and found no non-blocking ssh client. PHP has the SSH2 extension. In theory, a command-based SSH client can be implemented using standard input and output, in this way, the inconvenience caused by the network problem is solved, so a PHP non-blocking SSH client is developed.

Value:

  • It solves the problem of network latency and packet loss to the greatest extent based on commands.
  • The test is successful in windows and Linux.

Disadvantages:

  • No auto-completion Function
  • No other functions such as sftp and scp
  • No color or bold display
  • In some cases, the display is not perfect.
  • Because it is almost no longer needed, we will not make any improvements for the moment.

Linux Running Effect

Running Effect in windows


Because it is a class in the framework, some general functions (such as debug_print () need to be provided by themselves. I will not rewrite it here.

The Code is as follows: Copy code

<? Php
Class FSSH {
Private $ conn;
Private $ shell;

/**
* Key = String password authentication, key = array ('pub' =>, 'pri '=>, 'type' =>, 'phrase' =>) key Authentication
* Two key authentication types are available: ssh-rsa and ssh-dss.
* $ Host [addr] = String address, $ host ['fp '] = array () server fingerprint
*/
Function _ construct ($ host, $ user, $ key ){
If (empty ($ host ['addr ']) {
Debug_print ('host cant't be empty', E_USER_ERROR );
}
If (empty ($ host ['fp']) {
Debug_print ('finger print is not specified ', E_USER_ERROR );
}
$ This-> stdin = fopen ('php: // stdin ', 'R ');
$ This-> stdout = fopen ('php: // stdout', 'w ');
If (false! = Strpos ($ host ['addr '],': ') {
$ Temp = explode (':', $ host ['addr ']);
$ Host ['addr '] = $ temp [0];
$ Port = $ temp [1];
} Else {
$ Port = 22;
}
If (is_string ($ key) | empty ($ key ['type']) {
$ Methods = null;
} Else {
$ Methods = array ('hostkey' => $ key ['type']);
}
$ Conn = ssh2_connect ($ host ['addr '], $ port, $ methods, array ('disconnect' => array ($ this, 'disconnect ')));
$ Fp = ssh2_fingerprint ($ conn, SSH2_FINGERPRINT_MD5 );
$ Success = false;
$ FpOK = false;
If (in_array ($ fp, $ host ['fp ']) {
$ FpOK = true;
} Else {
Fwrite ($ this-> stdout, "$ fpnIs fingerprint OK? (Y/n )");
$ Input = strtolower (stream_get_line ($ this-> stdin, 1 ));
If ($ input = 'y '){
$ FpOK = true;
} Else {
$ FpOK = false;
}
}
If ($ fpOK ){
If (is_array ($ key )){
If (ssh2_auth_pubkey_file ($ conn, $ user, $ key ['pub'], $ key ['pri '], $ key ['phrase']) {
$ Success = true;
} Else {
Debug_print ('Public Key Authentication failed', E_USER_ERROR );
}
} Elseif (is_string ($ key )){
If (ssh2_auth_password ($ conn, $ user, $ key )){
$ Success = true;
} Else {
Debug_print ('password Authentication failed', E_USER_ERROR );
}
}
} Else {
Debug_print ('fingerprint is invalid', E_USER_ERROR );
}
If ($ success ){
$ This-> conn = $ conn;
$ This-> shell = ssh2_shell ($ conn, null, null, 1024 );
}
Return $ success;
}

Function shell (){
// The Last Command
$ Last = '';
// End shell first and then while
$ SignalTerminate = false;
While (true ){
$ Cmd = $ this-> fread ($ this-> stdin );
$ Out = stream_get_contents ($ this-& gt; shell, 1024 );
If (! Empty ($ out) and! Empty ($ last )){
$ L1 = strlen ($ out );
$ L2 = strlen ($ last );
$ L = $ l1> $ l2? $ L2: $ l1;
$ Last = substr ($ last, $ l );
$ Out = substr ($ out, $ l );
}
Echo ltrim ($ out );
If ($ signalTerminate ){
Break;
}
If (in_array (trim ($ cmd), array ('exit '))){
$ SignalTerminate = true;
}
If (! Empty ($ cmd )){
$ Last = $ cmd;
Fwrite ($ this-> shell, $ cmd );
}
}
}

// There is no other way to solve the problem of reading windows command lines.
Private function fread ($ fd ){
Static $ data = '';
$ Read = array ($ fd );
$ Write = array ();
$ Response T = array ();
$ Result = stream_select ($ read, $ write, $ hour T );
If ($ result = false)
Debug_print ('stream _ select failed', E_USER_ERROR );
If ($ result! = 0 ){
$ C = stream_get_line ($ fd, 1 );
If ($ c! = Chr (13 ))
$ Data. = $ c;
If ($ c = chr (10 )){
$ T = $ data;
$ Data = '';
Return $ t;
}
}
}

Function _ destruct (){
Fclose ($ this-> stdin );
Fclose ($ this-> stdout );
$ This-> disconnect ();
}

Private function disconnect (){
If (is_resource ($ this-> conn )){
Unset ($ this-> conn );
Fclose ($ this-> shell );
}
}
}


Demo

The Code is as follows: Copy code

// $ Ssh = new FSSH (array ('add' => 'x. x. x. x: 22', 'fp '=> array (''), 'Tunnel', array ('pub' => 'e: Identity. pub', 'pri '=> 'e: Identity', 'type' => 'ssh-rsa '));
$ Ssh = new FSSH (array ('addr '=>' 192. 168.2.205 ', 'fp' => array ('54ecc700b844dcf0d40554a56109c01e '), 'root', '123 ');
$ Ssh-> shell ();

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.