使用 sftp 和 ssh2 的 fopen 分段错误

Segmentation fault on fopen using sftp and ssh2

我在 AWS 上有一个 php 系统 运行 和一个使用 [=15] 在外部服务器上传 xlsx 文件的 class =]shh2 和 sftp。 此代码工作正常,直到上次升级 aws 包 openssh-clients-6.6.1p1-31.62openssh-server-6.6.1p1-31.62这次我在 fopen 期间有一个 segfault。 Fopen 在外部服务器上创建一个文件。 这里的代码:

$stream = @fopen("ssh2.sftp://$this->sftp$remote_file", 'w');

然后我使用 $stream 来编写内容,但是代码停止在 fopen 上,因为出现段错误。 我没有找到关于这个问题的任何信息,我认为问题是 opnessh 的新升级,因为 php 代码没有改变。 有什么想法吗?

在 Whosebug 上找到答案:

自从这次 PHP 更新后,您必须用 intval():

包围您的主机部分(ssh2_sftp() 的结果)
$handle = opendir("ssh2.sftp://".intval($sftp)."/path/to/directory");

在我的例子中有 fopen 而不是 opendir,但解决方案是相同的。

我遇到了同样的错误,但我发现了这个 PHP bug(参见 post 来自:[2016-12-15 09:47 UTC] 作者:ovoelker 在 wavecon dot de)

  1. 添加php5-dev用于编译pecl模块
  2. 重新安装 ssh2 pecl 模块。
  3. 重新启动 apache 并正常工作

在我们的例子中,intval() 没有解决分段错误。但是,更改调用格式确实有效:

fopen("ssh2.sftp://{$username}:{$password}@{$host}:{$port}/{$absolutePath}/{$filename}", 'w');

如果您正在关闭与 ssh2_disconnect() 的连接,即使使用 intval($sftp) 解决方案,您也可能会遇到 "segmentation fault" 问题。正确的解决方案是在通过 unset($sftp)$sftp = null 关闭 SSH2 连接之前关闭 SFTP 连接。这是我读取远程文件的完整示例:

if (!$ssh2_connection = ssh2_connect($host, $port)) {
    die("Failed to connect\n");
}
if (!ssh2_auth_password($ssh2_connection, $username, $password)) {
    die("Failed to login\n");
}
if (!$sftp_connection = ssh2_sftp($ssh2_connection)) {
    die("Failed to open SFTP session\n");
}
if (!$fh = fopen("ssh2.sftp://".intval($sftp_connection).$path, 'r')) {
    die("Failed to open file\n");
}
while (($s = fgets($fh)) !== false) {
    echo $s;
}
fclose($fh);
unset($sftp_connection);
if (!ssh2_disconnect($ssh2_connection)) {
    die("Failed to disconnect\n");
}

P.S。此外,您可能会看到类似 "segmentation fault" 的内容:

php: channel.c:2570: _libssh2_channel_free: Assertion `session' failed.

Aborted

我的方案解决了。