PHP脚本在exec命令后挂起
我不熟悉PHP和PHP 我有以下代码:PHP脚本在exec命令后挂起,php,bash,ssh,phpseclib,Php,Bash,Ssh,Phpseclib,我不熟悉PHP和PHP 我有以下代码: $ssh = new Net_SSH2($_SESSION['targetAddress']); if (!$ssh->login(SSH_USER, SSH_PASSWORD)) { exit('Login Failed'); } $ssh->setTimeout(400); $a = 0; while(isset($file[$a])) { $ssh->exec('cd '.$_SESSION['path'].'
$ssh = new Net_SSH2($_SESSION['targetAddress']);
if (!$ssh->login(SSH_USER, SSH_PASSWORD)) {
exit('Login Failed');
}
$ssh->setTimeout(400);
$a = 0;
while(isset($file[$a])) {
$ssh->exec('cd '.$_SESSION['path'].'; find -L '.$file[$a].' > /tmp/ligacoes; for i in `cat /tmp/ligacoes`; do cp $i /var/tmp/; done');
$a++;
}
我在这里试图完成的是将用户在远程服务器上选择的文件复制到同一服务器上的新目录。在执行脚本时,它成功地找到第一个文件并将其复制到新目录,但之后脚本就停止了。即使用户只选择了一个项目,脚本也会挂起并且不会继续。它甚至不增加$a
对可能发生的事情有什么想法吗
更新:
我还直接在服务器上运行了这个命令,它工作得非常好。我想问题只限于$ssh->exec()代码>
更新2:
我更改了我的$ssh->exec('cd'.$\u SESSION['path'.];find-L'.$file[$a].>/tmp/ligacoes;对于'cat/tmp/ligacoes'中的I;do cp$I/var/tmp/;done')
到$ssh->exec('cd'.$\u SESSION['path'.];cp'.$file[$a]./var/tmp;')代码>解决了部分问题。现在,我可以将一个选定的文件复制到一个新目录,并且脚本不会挂起。当选择两个或多个文件时,该问题会不断发生。可能有帮助的事情:
$ssh->exec
同时回显stdout
和stderr
。检查一下李>
尝试一下echo$ssh->exec('echo hello')代码>
首先手动连接以确保“主机的真实性…是否确实要继续连接?”已被接受
一定要**手动检查每个命令,确保它们在通过脚本传输之前正常工作
在bash文件中放置一个命令示例,并尝试仅执行bash文件。如果可行,您可以通过exec()
将变量发送到bash文件进行处理。比如:
mybash.sh
cd /example/path/;
find -L example_file > /tmp/ligacoes;
for i in `cat /tmp/ligacoes`;
do cp $i /var/tmp/;
done
并在您的php中
$ssh->exec('mybash.sh');
如果这样做有效,那么您可以将其展开以发送变量
cd $1;
find -L $2 > /tmp/ligacoes;
for i in `cat /tmp/ligacoes`;
do cp $i /var/tmp/;
done
在$\u会话['path']
中这样调用它将是$1
:
$ssh->exec('mybash.sh '.$_SESSION['path'].' '.$file[$a]);
下面是超时的工作原理w.r.t.exec()
exec()方法的第一行是:
$this->curTimeout = $this->timeout;
稍后有一个while(true)
循环,其中包含以下行:
$temp = $this->_get_channel_packet(self::CHANNEL_EXEC);
\u get\u channel\u数据包
也有一个while(true)
循环。它循环直到超时或在适当的通道上接收数据。以下是超时代码:
if ($this->curTimeout) {
if ($this->curTimeout < 0) {
$this->is_timeout = true;
return true;
}
$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
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
$this->is_timeout = true;
return true;
}
$elapsed = microtime(true) - $start;
$this->curTimeout-= $elapsed;
}
我这样做需要20秒(尽管超时)。如果我注释掉$ssh->write()
,需要10秒。cat/dev/uradom\n
正在淹没客户端。通过实时日志(define('NET\u SSH2\u logging',3);
)可以更清楚地看到这一点。问题在于,瓶颈不是阻塞所花费的时间,而是接收数据/解密数据所花费的时间。瓶颈是$ssh->getLastError()
(返回字符串)和$ssh->getErrors()
(返回数组)。在你的问题中发布输出,如果有的话。这可以使用PHP完成,占用的资源更少。请参阅:@WEBjuju没有错误输出。使用$ssh->getLog()代码>我得到的唯一日志是连接成功。@kitson88 OP试图在远程系统上移动文件。我想说,按照Murilo的建议去做,并获取SSH2日志。要启用日志记录,您需要执行define('NET\u SSH2\u logging',2)代码>位于文件顶部。然后执行$ssh->getLog()
。将输出复制/粘贴到一个pastebin.com链接中,然后将该链接添加到您的问题中。我创建了一个bash文件,就像您所建议的那样。我能够执行它,但我得到了相同的结果:我的PHP脚本停止。我在echo$ssh->exec('grava1.sh')中没有得到任何输出代码>,甚至是成功复制的第一个文件。只需尝试echo$ssh->exec('echo hello')代码>还要确保您已经接受了第一次通过ssh连接时收到的中间人警告(请参阅上面的新#3)好的,我在执行echo$ssh->exec('echo hello')时收到“hello”代码>。我手动连接,一切似乎都准备好了。@MuriloKomirchuk嗯,听起来你离得越来越近了。一步一个脚印。接下来,我可能会将echo hello
添加到shell脚本中。尝试修改权限直到它工作(我建议初学者使用chmod700
)。
$ssh->write("cat /dev/urandom\n");
$ssh->setTimeout(10);
$start = microtime(true);
echo $ssh->exec('ping google.com');
$elapsed = microtime(true) - $start;
echo "took $elapsed seconds\n";