繁体   English   中英

exec命令后PHP脚本挂起

[英]PHP script hangs after exec command

我是PHP和SSHphpseclib实现新手

我有以下代码:

$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

对可能发生的事情的任何想法?

更新:

实时NET_SSH2日志

我也直接在服务器上运行命令,它运行正常。 我想这个问题仅限于$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;'); 这解决了部分问题。 现在,我可以将一个选定的文件复制到新目录,脚本不会挂起。 选择两个或多个文件时,问题仍然存在。

可能有帮助的事情:

  1. $ssh->exec stdoutstderr 检查那些。
  2. 试试echo $ssh->exec('echo hello');
  3. 首先手动连接以确保“主机的真实性......您确定要继续连接吗?” 已被接受。
  4. 一定要将**检查每个命令的手动,以确保他们通过你的脚本管道之前工作。
  5. 一个命令示例放在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

这样称它为$_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM