【问题标题】:PHPSECLIB: Fatal error: Uncaught exception 'RuntimeException' with message 'Connection closed by server'PHPSECLIB:致命错误:未捕获的异常“RuntimeException”,消息“连接被服务器关闭”
【发布时间】:2016-03-14 16:37:23
【问题描述】:

这是我第一次在这里发布问题,请多多包涵。我对这个问题束手无策。下面已经非常详细地描述了这个问题。我正在寻找的是运行 phpseclib 脚本后发生以下错误的潜在原因和可能的补救措施...

致命错误:在 /home/electroline_admin/orders.electrolineelectronics.com/classes/phpseclib/Net/SSH2.php:1075 中未捕获异常“RuntimeException”和消息“服务器关闭连接”

堆栈跟踪:

/home/electroline_admin/orders.electrolineelectronics.com/classes/phpseclib/Net/SSH2.php(1877): phpseclib\Net\SSH2->_connect() [内部函数]: phpseclib\Net\SSH2->_login('electroline', 'Bitter8Steal_Wr...')

/home/electroline_admin/orders.electrolineelectronics.com/classes/phpseclib/Net/SFTP.php(394): call_user_func_array(数组, 数组)

/home/electroline_admin/orders.electrolineelectronics.com/classes/class.orders.php(4974): phpseclib\Net\SFTP->login('electroline', 'Bitter8Steal_Wr...')

/home/electroline_admin/orders.electrolineelectronics.com/live_orders_test.php(31): 订单->ftp_in_nd(Array, '1383317685.md5E...', '/home/electroli...')

{main} 投入 /home/electroline_admin/orders.electrolineelectronics.com/classes/phpseclib/Net/SSH2.php 在线 1075 electroline_admin@ps80038:~$ /usr/local/php54/bin/php /home/electroline_admin/orders.electrolineelectronics.com/live_orders_test.php

是否针对类似问题进行了所有勤奋的研究,但似乎没有任何东西指向有意义的答案。我最初的怀疑是存在超时问题,因为这个脚本正在调用和提取大小不一的批量文件。所以我增加了超时限制,但未能解决问题。

任何见解都将不胜感激。谢谢!!!

下面提供了详细的代码概述......

导致错误的代码如下...

public function pending_ftp()
{
    $dumped_arr = array('MAM');
    $cust_query = "SELECT DISTINCT `ID` AS ID,`CHUB` AS CH FROM `$this->tbl_cu`";
    $res_cust = $this->query($cust_query);

    if($res_cust[1])
    {
        while($cust_arr = mysql_fetch_array($res_cust[0],MYSQL_ASSOC))
        {
            $cust = $cust_arr['ID'];
            $chub = $cust_arr['CH'];
            if($chub == 'Y') $stg = $this->chub_ftp_settings($cust);
            elseif($cust == 'QBD') $stg = array('URL' => 'edi.esadmin.com','USR' => 'Electroline','PSW' => 'tVd&hP4','PRT' => 21,'DIR' => '/to_Electroline');
            else $stg = false;

            $pend_dir = '/home/electroline_admin/orders.electrolineelectronics.com/pending/'.strtolower($cust);

            if($stg)
            {
                $new_files = $this->ftp_get_filelist($stg); // METHOD CALLING PHPSECLIB CALLABLE

                foreach($new_files as $inx => $file_path)
                {
                    $file_info = pathinfo($file_path);
                    $file = $file_info['basename'];
                    $pend_path = $pend_dir.'/'.$file;
                    $ftp_sts = $this->ftp_in_nd($stg,$file,$pend_path); // METHOD CALLING PHPSECLIB CALLABLE
                }
            }
            elseif(in_array($cust,$dumped_arr))
            {
                $dump_dir = '/home/electroline_admin/orders.electrolineelectronics.com/dump/'.strtolower($cust);
                $dump_files = scandir($dump_dir);
                $not_a_file = array('.','..');

                foreach($dump_files as $inx => $file)
                {
                    if(!in_array($file,$not_a_file))
                    {
                        $dump_path = $dump_dir.'/'.$file;
                        $pend_path = $pend_dir.'/'.$file;

                        if(file_exists($dump_path)) $dump_copy = copy($dump_path,$pend_path);
                    }
                }
            }
        }
    }
}

...封装phpseclib callable的具体方法如下

public function ftp_in_nd($settings,$remote_file,$local_path)
{
    if(isset($settings))
    {
        $furl = $settings['URL'];
        $fusr = $settings['USR'];
        $fpwd = $settings['PSW'];
        $fprt = is_numeric($settings['PRT']) && $settings['PRT'] > 0 ?  $settings['PRT'] : 21;
        $fdir = strlen($settings['DIR']) > 0 ? $settings['DIR'] : ''; 

        if($fprt == 22)
        {
            $fcon = new \phpseclib\Net\SFTP($furl,$fprt,30); // PHPSECLIB

            if($fcon->login($fusr,$fpwd)) // PHPSECLIB
            {
                $fmsg = "SFTP LOGIN SUCCESS ($fusr): $furl".(is_numeric($fprt) ? " on port $fprt" : '')." on ".date('Y-m-d @ H:i:s',time())."\r\n";
                $fmsg .= "FILE DOWNLOAD ATTEMPT ".date('Y-m-d @ H:i:s',time())."\r\n";

                $fcon->chdir($fdir);

                if($fcon->get($remote_file,$local_path)) // PHPSECLIB
                {
                    $fmsg .= "FILE DOWNLOADED ".date('Y-m-d @ H:i:s',time())."\r\n";

                    if(file_exists($local_path))
                    {
                        $fmsg .= "DOWNLOAD SUCCESSFULLY VERIFIED ".date('Y-m-d @ H:i:s',time())."\r\n";
                        $fstat = "SUCCESS";
                    }
                    else
                    {
                        $fmsg .= "DOWNLOAD NOT VERIFIED ".date('Y-m-d @ H:i:s',time())."\r\n";
                        $fstat = "UNVERIFIED";
                    }

                    goto bottom;
                }
                else
                {
                    $fmsg .= "FILE DOWNLOAD FAIL ".date('Y-m-d @ H:i:s',time())."\r\n";
                    $fstat = "FAIL";    
                    goto bottom;
                }
            }
            else
            {
                $fmsg .= "SFTP LOGIN FAIL ($fusr): file transfer attempt aborted on ".date('Y-m-d @ H:i:s',time())."\r\n";
                $fstat = "FAIL";
                goto bottom;
            }
        }
        else
        {
            if($fcon = ftp_connect($furl,(is_numeric($fprt) ? $fprt : 21)))
            {
                $fmsg = "FTP CONNECT SUCCESS: $furl".(is_numeric($fprt) ? " on port $fprt" : '')." on ".date('Y-m-d @ H:i:s',time())."\r\n";

                if(ftp_login($fcon,$fusr,$fpwd))
                {
                    $fmsg .= "FTP LOGIN SUCCESS ($fusr): $furl".(is_numeric($fprt) ? " on port $fprt" : 21)." on ".date('Y-m-d @ H:i:s',time())."\r\n";
                    $fmsg .= "FILE DOWNLOAD ATTEMPT ".date('Y-m-d @ H:i:s',time())."\r\n";

                    ftp_chdir($fcon,$fdir);

                    if(ftp_get($fcon,$local_path,$remote_file,FTP_BINARY))
                    {
                        $fmsg .= "FILE DOWNLOADED ".date('Y-m-d @ H:i:s',time())."\r\n";

                        if(file_exists($local_path))
                        {
                            $fmsg .= "DOWNLOAD SUCCESSFULLY VERIFIED ".date('Y-m-d @ H:i:s',time())."\r\n";
                            $fstat = "SUCCESS";
                        }
                        else
                        {
                            $fmsg .= "FILE DOWNLOAD NOT VERIFIED ".date('Y-m-d @ H:i:s',time())."\r\n";
                            $fstat = "UNVERIFIED";  
                        }

                        goto bottom;
                    }
                    else
                    {
                        $fmsg .= "FILE DOWNLOAD FAIL ".date('Y-m-d @ H:i:s',time())."\r\n";
                        $fstat = "FAIL";
                        goto bottom;
                    }
                }
                else
                {
                    $fmsg .= "FTP LOGIN FAIL ($fusr): file transfer attempt aborted on ".date('Y-m-d @ H:i:s',time())."\r\n";
                    $fstat = "FAIL";
                    goto bottom;
                }
            }
            else
            {
                $fmsg = "FTP CONNECT FAIL: file transfer attempt aborted on ".date('Y-m-d @ H:i:s',time())."\r\n";
                $fstat = "FAIL";
                goto bottom;
            }
        }
    }
    else
    {
        $fmsg = "FTP SETTINGS NOT PROVIDED: file transfer attempt aborted on ".date('Y-m-d @ H:i:s',time())."\r\n";
        $fstat = "FAIL";
        goto bottom;
    }

    bottom:

    if(!isset($fmsg)) $fmsg = "FTP NOT PROCESSED: process abandoned on ".date('Y-m-d @ H:i:s',time())."; check settings and reprocess\r\n";
    if(!isset($fstat)) $fstat = "FAIL";

    $stat['SID'] = $fstat;
    $stat['MSG'] = $fmsg;

    return $stat;
}

根据我自己的操作和情报收集,当从 phpseclib SSH2 类调用此方法时,似乎发生了连接失败...

function _connect()
{
    if ($this->bitmap & self::MASK_CONSTRUCTOR) {
        return false;
    }

    $this->bitmap |= self::MASK_CONSTRUCTOR;

    $this->curTimeout = $this->timeout;

    $this->last_packet = microtime(true);

    if (!is_resource($this->fsock)) {
        $start = microtime(true);
        $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout);
        if (!$this->fsock) {
            $host = $this->host . ':' . $this->port;
            throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr"));
        }
        $elapsed = microtime(true) - $start;

        $this->curTimeout-= $elapsed;

        if ($this->curTimeout <= 0) {
            $this->is_timeout = true;
            return false;
        }
    }

    /* According to the SSH2 specs,

      "The server MAY send other lines of data before sending the version
       string.  Each line SHOULD be terminated by a Carriage Return and Line
       Feed.  Such lines MUST NOT begin with "SSH-", and SHOULD be encoded
       in ISO-10646 UTF-8 [RFC3629] (language is not specified).  Clients
       MUST be able to process such lines." */
    $temp = '';
    $extra = '';
    while (!feof($this->fsock) && !preg_match('#^SSH-(\d\.\d+)#', $temp, $matches)) {
        if (substr($temp, -2) == "\r\n") {
            $extra.= $temp;
            $temp = '';
        }

        if ($this->curTimeout) {
            if ($this->curTimeout < 0) {
                $this->is_timeout = true;
                return false;
            }
            $read = array($this->fsock);
            $write = $except = null;
            $start = microtime(true);
            $sec = floor($this->curTimeout);
            $usec = 1000000 * ($this->curTimeout - $sec);
            // on windows this returns a "Warning: Invalid CRT parameters detected" error
            // the !count() is done as a workaround for <https://bugs.php.net/42682>
            if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
                $this->is_timeout = true;
                return false;
            }
            $elapsed = microtime(true) - $start;
            $this->curTimeout-= $elapsed;
        }

        $temp.= fgets($this->fsock, 255);
    }

    **if (feof($this->fsock)) {
        throw new \RuntimeException('Connection closed by server');
    }  // SCRIPT FAILS HERE!!! **

    $this->identifier = $this->_generate_identifier();

    if (defined('NET_SSH2_LOGGING')) {
        $this->_append_log('<-', $extra . $temp);
        $this->_append_log('->', $this->identifier . "\r\n");
    }

    $this->server_identifier = trim($temp, "\r\n");
    if (strlen($extra)) {
        $this->errors[] = utf8_decode($extra);
    }

    if ($matches[1] != '1.99' && $matches[1] != '2.0') {
        throw new \RuntimeException("Cannot connect to SSH $matches[1] servers");
    }

    fputs($this->fsock, $this->identifier . "\r\n");

    $response = $this->_get_binary_packet();
    if ($response === false) {
        throw new \RuntimeException('Connection closed by server');
    }

    if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
        throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT');
    }

    if (!$this->_key_exchange($response)) {
        return false;
    }

    $this->bitmap|= self::MASK_CONNECTED;

    return true;
}

【问题讨论】:

    标签: php phpseclib


    【解决方案1】:

    嗯,我可以正常连接:

    <?php
    include('Net/SSH2.php');
    
    define('NET_SSH2_LOGGING', 2);
    
    $ssh = new Net_SSH2('orders.electrolineelectronics.com');
    $ssh->login('zzz', 'zzz');
    
    echo $ssh->getLog();
    

    我的意思是,我无法成功进行身份验证,但我可以尝试进行身份验证。

    鉴于此,我的猜测是问题出在尝试建立连接的计算机上。与环境有关的东西。也许你安装了 selinux,默认情况下会阻止 fsockopen 正常工作:

    http://yml.com/fv-b-1-619/selinux--apache-httpd--php-establishing-socket-connections-using-fsockopen---et-al.html

    或者您的主机可能有 orders.electrolineelectronics.com 指向其他没有安装 SSH 服务器或其他东西的 IP 地址。

    可能是任何数量的问题,但我能够很好地连接到 phpseclib 的事实让我认为问题是环境问题。特别是因为它在实际发送任何数据之前就死了(假设你的分析是正确的)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-19
      • 2015-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-09
      相关资源
      最近更新 更多