I'm new to PHP and the phpseclib implementation of SSH.
I have the following code :
$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++;
}
What I am trying to accomplish here is to copy files chosen by user on a remote server to a new directory on the same server. When executing the script, it successfully find and copy the first file to the new directory, but after that the script just stops. Even if the user choose just one item the script hangs and does not continue. It doesn't even increment $a
Any thoughts on what may be happening ?
UPDATE:
I also ran the command directly in the server and it works perfectly. I guess the issue is limited to $ssh->exec();
UPDATE 2:
I changed my $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;');
and that solved part of the problem. Now I am able to copy one selected file to a new directory and the script does not hang. The issue keeps happening when two or more files are selected.
答案 0 :(得分:3)
可能会有所帮助的事情:
$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]);
称为
Decorator pattern
答案 1 :(得分:0)
这是超时工作的原因w.r.t. 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->write()
它需要10秒。 cat /dev/urandom\n
只是充斥着客户端。您可以通过实时日志记录(define('NET_SSH2_LOGGING', 3);
)更清楚地看到这一点。问题在于瓶颈不是阻塞所花费的时间,而是接收数据/解密所花费的时间。