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


Sending input to the blocking stream of PHP ssh

我的情况与下面的问题类似SSH2更改用户密码

唯一的区别是我的操作是"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;
        }
    }

以下是如何使用phpseclib,一个纯PHP SSH2实现:

<?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();

scp(以及ssh)不需要密码,而是来自标准输入,而是来自控制台(如tty),这是一件好事。将密码存储在任何地方(例如某些PHP代码)都会损害ssh的用途。

相反,您应该创建一个RSA身份验证密钥。这里有一个简单的操作方法。

完成后,按如下方式更改命令行:

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

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