Не удается заставить SFTP работать в PHP
Я пишу простой 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 extenstion с SFTP? Я пропустил что-то очевидное здесь?
UPDATE:
Я устанавливаю sftp на другой машине внутри, и он работает нормально. Итак, должно быть что-то о том, что сервер, с которым я пытаюсь подключиться, не работает.
Ответы
Ответ 1
При подключении к SFTP-серверу вам необходимо подключиться к корневой папке (например, для чтения содержимого папки), вы все равно получите ошибку при использовании только "/" в качестве пути.
Решение, которое я нашел, это использовать путь "/./", который является допустимым путем, который ссылается на корневую папку. Это полезно, когда пользователь, с которым вы регистрируетесь, имеет доступ только к своей корневой папке и полный путь не доступен.
Таким образом, запрос на сервер при попытке прочитать содержимое корневой папки должен выглядеть примерно так:
$rd = "ssh2.sftp://{$this->sftp}/./";
Ответ 2
Для версий 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
Ответ 3
У меня такая же проблема. Я предполагаю, что вы делаете что-то похожее на это:
$dir = "ssh2.sftp://{$sftp}{$remote_dir}";
$handle = opendir($dir);
Когда $remote_dir
- полный путь от корня, тогда работает open_dir
. Если $remote_dir
- это просто '/' или '', тогда я получаю ошибку "неспособность открыть", как вы это делали.
В моем случае кажется, что ssh подключается в корневой папке вместо каталога "home", как это делает ftp. Вы упомянули, что он работал на другом сервере, поэтому я задаюсь вопросом, просто ли это проблема с конфигурацией.
Ответ 4
Самый простой способ заставить 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();
?>
Ответ 5
Документация на этой странице содержит ошибку. Взгляните сюда на пример: http://php.net/ssh2_sftp - вам действительно нужно открыть специальный SFTP-ресурс, используя ssh2_sftp() ранее использовать его с fopen(). И да, это выглядит так, например, "Ресурс № 24" при преобразовании в строку... немного странно, но, по-видимому, он работает.
Другой оговоркой является то, что SFTP запускается в корневом каталоге, а не в домашнем каталоге удаленного пользователя, поэтому ваш удаленный путь в URI всегда должен быть абсолютным.
Ответ 6
У меня была одна и та же проблема, но я мог понять проблему.
В моем случае, когда я подключался к серверу, я направлялся в корневую учетную запись, и из-за конфигураций сервера я не мог там писать.
Я подключился к учетной записи с помощью fireFTP, и поэтому я мог видеть, где был корень учетной записи... это был корень сервера.
Мне пришлось включить весь путь до папки, где мне разрешено писать, и поэтому я мог бы решить проблему.
Итак, мой совет - получить путь с использованием графического интерфейса (я использовал fireFTP) и добавить весь путь к вашему коду.
$pathFromAccountRootFolderToMyDestinationFolder = '/Account/Root/Folder/To/My/Folder';
$stream = fopen("ssh2.sftp://".$sftp."/".$pathFromAccountRootFolderToMyDestinationFolder."/myFile.ext", 'r');
Надеюсь, это поможет вам и другим людям с той же проблемой!
Ура!
Ответ 7
Недавно я попытался заставить SFTP работать с PHP и обнаружил, что phpseclib намного проще в использовании:
http://phpseclib.sourceforge.net/
Если у вас есть роскошь не быть на общем хосте и вы можете устанавливать любые расширения, которые вы хотите, возможно, расширение PECL было бы лучше, но не всем нам повезло. Кроме того, API phpseclib выглядит немного интуитивно понятным, будучи ООП и все.
Ответ 8
Моя проблема заключалась в том, что я подключался к функции и возвращал строковый URL-адрес с ресурсом внутри. Unfortunatelly ресурс, чем создан в контексте функции, и сборщик мусора отключает ресурс на конце функции. Решение: вернуть ресурс по ссылке и вручную удалить его в более сложном контексте.
Ответ 9
Решил мою проблему, включив поддержку sftp на сервере (Powershell)