[英]PHP script hangs after exec command
我是PHP和SSH的phpseclib实现的新手 。
我有以下代码:
$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 '.$_SESSION['path'].'; find -L '.$file[$a].' > /tmp/ligacoes; for i in 'cat /tmp/ligacoes'; do cp $i /var/tmp/; done');
to $ssh->exec('cd '.$_SESSION['path'].'; cp '.$file[$a].' /var/tmp;');
这解决了部分问题。 现在,我可以将一个选定的文件复制到新目录,脚本不会挂起。 选择两个或多个文件时,问题仍然存在。
可能有帮助的事情:
$ssh->exec
stdout
和stderr
。 检查那些。 echo $ssh->exec('echo hello');
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
这样称它为$_SESSION['path']
为$1
:
$ssh->exec('mybash.sh '.$_SESSION['path'].' '.$file[$a]);
这是超时工作与exec()的关系。
所以exec()方法的第一行是这样的:
$this->curTimeout = $this->timeout;
后来有一段while (true)
循环,其中包含以下内容:
$temp = $this->_get_channel_packet(self::CHANNEL_EXEC);
_get_channel_packet
也有一个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;
}
stream_select
阻塞,直到可以读取数据。 根据SSH服务器的行为,它可以很好地阻止400秒。 谁知道......也许在您的系统上, stream_select
会在达到400s之前崩溃。
也就是说,在该函数上启用了错误抑制,如stream_select
调用上方的注释中所述。 您可以删除可能提供一些见解的错误抑制。
另外,请记住,超时仅跟踪数据可用的时间。 例如,解密所花费的时间不计入超时。
例如...
$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";
我这样做, $ssh->exec()
需要20 $ssh->exec()
(尽管超时)。 如果我注释掉$ssh->write()
则需要10秒。 cat /dev/urandom\\n
只是充斥客户端。 您可以通过实时日志记录更清楚地看到这一点( define('NET_SSH2_LOGGING', 3);
)。 问题在于瓶颈不是阻塞所花费的时间,而是接收数据/解密所花费的时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.