我遇到了从ssh连接中检测流结束的麻烦。这就是我的尝试:
<pre><?php
if (!function_exists("ssh2_connect")) die("function ssh2_connect doesn't exist");
if(!($con = ssh2_connect("localhost", 22)))
echo "fail: unable to establish connection\n";
else
if(!$ssh = ssh2_auth_password($con, "viassh", "sshpass")) {
echo "fail: unable to authenticate\n";
}
$sshStream = ssh2_shell($con, 'xterm', null, 80, 24, SSH2_TERM_UNIT_CHARS);
$strCommand = 'cd /var/www/test';
fwrite($sshStream, $strCommand . PHP_EOL);
stream_set_blocking($sshStream, true);
// infinite loop
#$stderr_stream = fgets(ssh2_fetch_stream($sshStream, SSH2_STREAM_STDERR), 8192);
#var_dump($stderr_stream);
// infinite loop
#var_dump(stream_get_contents($sshStream));
$ret = "";
while ($buf = fgets($sshStream)) {
$ret .= $buf;
// always false
#$meta = stream_get_meta_data($sshStream);
#var_dump($meta['eof']);
// works
if(strpos($buf, '$ cd ') !== false) break;
}
$strCommand = 'git status';
fwrite($sshStream, $strCommand . PHP_EOL);
stream_set_blocking($sshStream, true);
while ($buf = fgets($sshStream)) {
$ret .= $buf;
if (strpos($buf, '-a') !== false) break;
}
fclose($sshStream);
echo $ret;
?>
给了我正确的输出:
Welcome to Ubuntu 12.04.1 LTS (GNU/Linux 3.2.0-32-generic-pae i686)
* Documentation: https://help.ubuntu.com/
20 packages can be updated.
0 updates are security updates.
Last login: Tue Oct 23 16:45:20 2012 from localhost
cd /var/www/test
]0;viassh@rcdev: ~viassh@rcdev:~$ cd /var/www/test
git status
]0;viassh@rcdev: /var/www/testviassh@rcdev:/var/www/test$ git status
# On branch develop
# Changes not staged for commit:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: ssh_1.php
# modified: ssh_1.php~
# modified: ssh_shell.php
# modified: ssh_shell.php~
#
# Untracked files:
# (use "git add ..." to include in what will be committed)
#
# ssh_stream1.php
# ssh_stream1.php~
no changes added to commit (use "git add" and/or "git commit -a")
但仅仅因为我知道了流的最后一行。我试过feof(),但那也失败了。 所以希望有人可以帮助我。
答案 0 :(得分:0)
似乎您可以使用phpseclib, a pure PHP SSH implementation轻松完成此操作?:
<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('Login Failed');
}
echo $ssh->exec('git status');
?>
也许我不明白你想要做什么呢?
答案 1 :(得分:0)
看起来这是已知行为。 http://php.net/manual/en/function.ssh2-shell.php
你想做什么?
答案 2 :(得分:0)
我知道这是一个老问题,但我想添加我的输入,因为我无法在线找到正常工作的代码段。 phpseclib并不总是一个合适的替代品 - 特别是,它缺乏按顺序执行命令的可靠方法。我发现PHP扩展更可靠,也更容易使用。
我的解决方案如下,在我们的设置中似乎很有效。原理很简单:要求系统在输出之前打印BEGIN消息,在输出之后输出END消息(base64用于此,但还有很多其他方法)。该函数在返回在标记之间打印到控制台的任何内容之前等待END。
function executeCommand($connection, $command)
{
$shell = ssh2_shell($connection, 'xterm');
sleep(1);
stream_set_blocking($shell, true);
printf("Running command: %s\n\n", $command);
fwrite($shell, 'echo "LS0tLUJFR0lOLS0tLQo=" | base64 --decode;'.$command.';printf "\n";echo "LS0tLUVORC0tLS0K" | base64 --decode;'.PHP_EOL);
$output = '';
$output_start = false;
while (true) {
$buffer = fgets($shell);
flush();
if(strpos($buffer, "----BEGIN----") !== false) {
$output_start = true;
continue;
}
if(strpos($buffer, "----END----") !== false) {
break;
}
if($output_start) {
printf("%s\n", $buffer);
$output .= $buffer."\n";
}
}
print("Finished executing command\n");
fclose($shell);
print("Shell closed\n");
return trim($output);
}