将输入发送到PHP ssh的阻塞流

时间:2013-07-04 11:45:05

标签: php ssh stream blocking

我有类似以下问题的情况 SSH2 change a user password

唯一的区别是我的动作是“scp”,我想通过PHP发送ssh命令使用scp命令将文件发送到远程机器(我知道php本身有实现这个的方法,但出于某种原因,我跳过那个方法)。

Code is as follows



//run specified cmd with stream reading and writing
    function runCMDAdvance($cmd){
        if (strpos($cmd,'scp') !== false) {
                        //reply machine when ask for password in file transfer
            $confirmPass = $this->password."\n".$this->password."\n";
            if (!($stream = ssh2_exec($this->conn, $cmd )))
            {
                echo "fail: unable to execute command\n";
                fclose($stream);
                return ERROR_SSH_EXEC_COMM;
            }

            fwrite($stream,$confirmPass); //>>Actually I want to pass the password information by writing to the stream, but turn out that it does not work
            stream_set_blocking($stream, true);
        }
    }

当我尝试在流集阻塞后写入密码信息时,php执行代码将卡住。 (我想原因是远程机器正在等待密码信息但是php无法提供它们,所以它只是等待并阻塞php运行的线程。)

我已经阅读了上述问题,但似乎无法找到实现这一目标的正确方向,对此有什么想法吗?

再次感谢大家的帮助!

参考neubert的回答,使用phpseclib仍无效......

//$cmd is $cmd =  'scp '.$scpPath.' root@'.$ip.':/root';
function runCMDAdvance($cmd, $tVal){

        if (strstr($cmd,"scp")!==FALSE){
            if((include('Net/SSH2.php')) && (include('Net/SCP.php'))){
                //set ssh timeout value
                $this->setTimeoutVar($tVal);

                $ssh = new Net_SSH2($this->host);
                if (!$ssh->login($this->username, $this->password)){
                    echo "Bad Login";
                    return false;
                }
                $ssh->write($cmd."\n");
                $ssh->read(' password:');
                $ssh->write($this->password."\n");
            }
        }
        else{
            echo "Wrong command used, please check your code";
            return false;
        }
    }

我处理SSH读写流的解决方案

//run any specified cmd using ssh
    //parameter:
    //cmd>>running command
    //tVal>>command run timeout
    //return:terminal stdout
    function runCMDAdvance($sshIP, $cmd, $tVal,$tarIP){
        $ssh = new Net_SSH2($sshIP);
        if (!$ssh->login($this->username, $this->password)){
            echo "Bad Login";
            return false;
        }
        //set timeout for running ssh command, should be done after the ssh object has been initialized
        $ssh->setTimeout($tVal);

        //scp action detected
        if (strstr($cmd,"scp")!==FALSE){
            //if this is the first time to do the ssh, connect with "yes" for answering
            if ($ssh->write($cmd)){
                //store the output of the text message given by the router
                $ssh_stdout = $ssh->read();
                //echo $ssh_stdout."|||";
                if (strstr($ssh_stdout,'trusted ')!==FALSE){
                    $ssh->write("y\n");
                    //and ask password
                    $ssh->read(' :password');
                }
                //deal with known host situation
                elseif (strstr($ssh_stdout,'ssh-keygen ')!==FALSE){
                    $ssh->write('ssh-keygen -f '.'/root/.ssh/known_hosts -R '.$tarIP."\n");
                    $ssh->write($cmd);
                    $ssh->read(' :password');
                    $ssh->write($this->password."\n");
                    return true;
                }
                //deal with still connecting situation
                elseif (strstr($ssh_stdout,'Are you sure you want to continue connecting')!==FALSE){
                    $ssh->write("yes\n");
                    $ssh->read(' :password');
                    $ssh->write($this->password."\n");
                    return true;
                }
                $ssh->write($this->password."\n");
                $returnRead = $ssh->read();
                $ssh->disconnect();
                return true;
            }//end of inner inner if
        }//end of scp if (deal with scp)
        else{//if not scp action,just normal action,simply execute the command
            //exec will not return anything if the command is not run successfully
            $res = $ssh->exec($cmd);
            $ssh->disconnect();
            return $res;
        }
    }

2 个答案:

答案 0 :(得分:0)

scp(以及ssh)不希望输入密码,而是来自标准输入,但来自控制台(如tty),这是一件好事。在任何地方存储密码(如某些PHP代码)都会影响ssh的目的。

相反,您应该创建一个RSA身份验证密钥。 Here is a simple how-to

完成后,按如下所示更改命令行:

scp -i /path/to/your/rsa.private.key

确保将此私钥存储在“安全”位置。它必须可以从PHP脚本访问,但不能访问其他人。特别是不要通过URL访问它。

答案 1 :(得分:0)

以下是使用phpseclib, a pure PHP SSH2 implementation

执行此操作的方法
<?php
include('Net/SSH2.php');

define('NET_SSH2_LOGGING', 3);

$ssh = new Net_SSH2('www.website1.com');
$ssh->login('username', 'password');

$ssh->write("ssh username@www.website2.com\n");
$ssh->read(' password:');
$ssh->write("password\n");

$ssh->setTimeout(0.5);
echo $ssh->read();