Вопрос

Я пишу простой SFTP-клиент на PHP, потому что нам необходимо программно получать файлы через n удаленных серверов.Я использую расширение PECL SSH2.

Однако я наткнулся на блокпост.Документация на php.net предполагает, что вы можете сделать это:

$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r');

Однако у меня есть метод ls, который пытается сделать что-то подобное

public function ls($dir)
{
    $rd = "ssh2.sftp://{$this->sftp}/$dir";
    $handle = opendir($rd);
    if (!is_resource($handle)) {
        throw new SFTPException("Could not open directory.");
    }

    while (false !== ($file = readdir($handle))) {
        if (substr($file, 0, 1) != '.'){
            print $file . "\n";
        }
    }
    closedir($handle);
}

Я получаю следующую ошибку:

PHP Warning:  opendir(): Unable to open ssh2.sftp://Resource id #5/outgoing on remote host

Это имеет смысл, потому что именно это происходит, когда вы преобразуете ресурс в строку.Документация неправильная?Я попробовал заменить ресурс хостом, именем пользователя и хостом, но это тоже не сработало.Я знаю, что путь правильный, потому что я могу запустить SFTP из командной строки, и он работает нормально.

Кто-нибудь еще пытался использовать расширение SSH2 с SFTP?Я упускаю здесь что-то очевидное?

ОБНОВЛЯТЬ:

Я настраиваю sftp на другой машине, и все работает нормально.Итак, что-то в сервере, к которому я пытаюсь подключиться, не работает.

Это было полезно?

Решение

При подключении к SFTP-серверу и необходимости подключения к корневой папке (например, для чтения содержимого папки) вы все равно получите сообщение об ошибке, если в качестве пути используете только «/».

Решение, которое я нашел, заключалось в использовании пути «/./», это действительный путь, ссылающийся на корневую папку.Это полезно, когда пользователь, с которым вы входите в систему, имеет доступ только к своей корневой папке и полный путь не доступен.

То есть запрос к серверу при попытке прочитать содержимое корневой папки должен быть примерно таким:

$rd = "ssh2.sftp://{$this->sftp}/./";

Другие советы

Для версий PHP > 5.6.27 используйте intval()

$sftpConnection = ssh2_connect($host);
$sftp = ssh2_sftp($sftpConnection);
$fp = fopen("ssh2.sftp://" . intval($sftp) . $remoteFile, "r");

https://bugs.php.net/bug.php?id=73597

У меня аналогичная проблема.Я предполагаю, что вы делаете что-то похожее на это:

    $dir = "ssh2.sftp://{$sftp}{$remote_dir}"; 
    $handle = opendir($dir);

Когда $remote_dir тогда это полный путь от корня open_dir работает.Если $remote_dir это просто '/' или '', тогда я получаю ошибку «невозможно открыть», как и вы.

В моем случае кажется, что ssh подключается к корневой папке, а не к «домашнему» каталогу, как это делает ftp.Вы упомянули, что это работало на другом сервере, поэтому мне интересно, не проблема ли это просто в конфигурации.

Самый простой способ заставить SFTP работать в PHP (даже в Windows) без установки каких-либо расширений и т. д. — это PHPSECLIB: http://phpseclib.sourceforge.net/ .SSH полностью реализован в классе PHP.

Вы используете это так:

<?php
include('Net/SFTP.php');

$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
    exit('Login Failed');
}

echo $sftp->pwd();
?>

Документация на этой странице содержит ошибку.Вместо этого взгляните на пример здесь: http://php.net/ssh2_sftp — на самом деле вам нужно открыть специальный SFTP-ресурс с помощью ssh2_sftp() перед его использованием с fopen().И да, это выглядит именно так, например.«Ресурс № 24» при преобразовании в строку...немного странно, но, видимо, это работает.

Еще одно предостережение: SFTP запускается в корневом каталоге, а не в домашнем каталоге удаленного пользователя, поэтому ваш удаленный путь в URI всегда должен быть абсолютным.

У меня была такая же проблема, но я смог понять проблему.

В моем случае при подключении к серверу я заходил в корень аккаунта и из-за конфигов сервера не мог туда писать.

Я подключился к учетной записи с помощью FireFTP и мог видеть, где находится корень учетной записи... это был корень сервера.

Мне пришлось указать весь путь до папки, в которую мне разрешено писать, чтобы я мог решить проблему.

Итак, мой совет — получить путь с помощью графического интерфейса (я использовал fireFTP) и добавить весь путь в свой код.


$pathFromAccountRootFolderToMyDestinationFolder = '/Account/Root/Folder/To/My/Folder';
$stream = fopen("ssh2.sftp://".$sftp."/".$pathFromAccountRootFolderToMyDestinationFolder."/myFile.ext", 'r');

Надеюсь, это поможет вам и другим людям с той же проблемой!

Ваше здоровье!

Недавно я попытался заставить работать SFTP на PHP и обнаружил, что phpseclib намного проще в использовании:

http://phpseclib.sourceforge.net/

Если вы можете позволить себе роскошь не находиться на общем хосте и можете установить любые расширения, которые захотите, возможно, расширение PECL будет лучше, но не всем нам так повезло.Кроме того, API phpseclib выглядит немного более интуитивно понятным, поскольку является ООП и все такое.

Моя проблема заключалась в том, что я подключался к функции и возвращал URL-адрес строки с ресурсом внутри.К сожалению, ресурс создается в контексте функции, а сборщик мусора отключает ресурс при завершении функции.Решение:вернуть ресурс по ссылке и отключить его вручную в более сложном контексте.

Решил мою проблему, включив поддержку sftp на сервере (Powershell).

Это ошибка в пакете ssh2, которую я нашел много лет назад и опубликовал исправление на php.net.Это устраняет эту проблему, но требует пересборки пакета ssh2 pecl.Вы можете прочитать больше здесь: https://bugs.php.net/bug.php?id=69981.Я включил исправление в файл ssh2_fopen_wrappers.c в пакете, чтобы устранить проблему.Вот комментарий, который я включил:

Вот строка кода из ssh2_fopen_wrappers.c, которая вызывает эту ошибку:(комментарий включен)

/*
       Find resource->path in the path string, then copy the entire string from the original path.
       This includes ?query#fragment in the path string
*/
    resource->path = estrdup(strstr(path, resource->path));

Эта строка кода (и, следовательно, эта ошибка) была введена как исправление ошибки № 59794.Эта строка кода пытается получить строку, содержащую часть, запрос и фрагмент, из переменной пути.Рассмотрим это значение для переменной пути:

ssh2.sftp://Resource id #5/topdir?a=something#heading1

Когда путь ресурса-> равен «/topdir», в результате «/topdir?a=something#heading1» присваивается пути ресурса->, как сказано в комментарии.

Теперь рассмотрим случай, когда ресурс->путь равен «/».После выполнения строки кода путь resources-> становится "//Resource id#5/topdir#heading1".Это явно не то, что вы хотите.Вот строка кода, которая делает:

 resource->path = estrdup( strstr( strstr( path, "//" ) + 2, "/" ) );

Вам также может потребоваться применить исправление для ошибки № 73597, которое удаляет «Идентификатор ресурса №» из строки пути перед вызовом php_url_parse().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top