2009-09-23 4 views
12

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

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

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

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

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 на другой машине, в доме, и она работает просто отлично. Итак, должно быть что-то о том, что сервер, с которым я пытаюсь подключиться, не работает.

+0

Можете ли вы подтвердить, что ssh2 соединение работает? как насчет использования любой из других функций ssh2? –

+0

ssh2_connect() ssh2_auth_password() ssh2_sftp() работают корректно. Насколько я могу судить, у меня есть действующий ресурс связи. –

ответ

35

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

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

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

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

Это правильный ответ. С тех пор между PHP 5.2 и 5.4 произошла ошибка, которая нарушила доступ к корневому каталогу. Спасибо за предоставление обходного пути! – 2013-05-06 23:11:30

+2

Я добавил ссылку на ваш ответ на https://bugs.php.net/bug.php?id=64169. – 2013-05-07 18:53:34

+3

Добро пожаловать @BradenAnderson, я нашел так много ответов здесь, что я думал, что предоставление того, что у меня было, было справедливым –

8

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

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

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

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

+1

Из того, что я видел, вы правы. Он подключается к корневому каталогу, а не к «дому». С помощью командной строки sftp клиент подключается к «home». Мне просто нужно получить абсолютный путь от клиента, к которому я пытаюсь подключиться. –

+0

'$ dir = 'ssh2.sftp: //'.$sftp.'/'.$absolute_path;' Использование абсолютного пути вместо исходного пути является ответом. – Aust

0

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

http://phpseclib.sourceforge.net/

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

+0

подходит только для некоторых версий sftp, указано в комментариях библиотек – Blacksonic

+1

99% установок SFTP используют v3. На самом деле, я никогда не сталкивался с сервером SFTP, который его не поддерживал. Многие клиенты также поддерживают только v3.Например, WinSCP. Добавление поддержки v6, когда v3 работает, и когда никто даже не использует v6, просто будет пустой тратой ресурсов dev. – 2013-07-11 15:02:44

+0

тогда вам повезло, но когда вам нужно переписать вещи из perl в php для многих клиентов, всегда есть 1%, которые используют другую версию. – Blacksonic

1

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

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

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

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

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


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

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

Приветствия!

+0

Это хорошая мысль. Я уже пробовал использовать FireZilla и WinSCP. Тем не менее я использовал то, что у них было, как абсолютный путь. –

+0

Есть ли способ получить реальный путь к домашнему каталогу пользователя? –

7

Самый простой способ получить работу 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(); 
?> 
3

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

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

0

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

13

Для 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

+2

Правильный ответ! Спасибо. –

+0

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

0

решаемые мою проблему, позволяя поддержку SFTP на сервере (Powershell)

Смежные вопросы