2009-09-23 18 views
12

Sto scrivendo un semplice client SFTP in PHP perché abbiamo la necessità di recuperare i file tramite server remoti in modo programmatico. Sto usando l'estensione PECL SSH2.Impossibile far funzionare SFTP in PHP

Ho incontrato un blocco stradale, però. La documentazione su php.net suggerisce che si può fare questo:

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

Tuttavia, ho un metodo di ls che cerca di qualcosa di simile

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); 
} 

ottengo il seguente errore:

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

Questo ha perfettamente senso perché è quello che succede quando lanci una risorsa in una stringa. La documentazione è sbagliata? Ho provato a sostituire la risorsa con host, nome utente e host e questo non ha funzionato neanche. So che il percorso è corretto perché posso eseguire SFTP dalla riga di comando e funziona bene.

Qualcun altro ha provato a utilizzare l'estensione SSH2 con SFTP? Mi sto perdendo qualcosa di ovvio qui?

UPDATE:

ha installato SFTP su un'altra macchina in-house e funziona bene. Quindi, ci deve essere qualcosa sul server che sto cercando di connettersi che non funziona.

+0

Puoi confermare che la connessione SSH2 sta lavorando? che ne dici di usare una delle altre funzioni di ssh2? –

+0

ssh2_connect() ssh2_auth_password() ssh2_sftp() funzionano tutti correttamente. Ho una risorsa di connessione valida per quanto posso dire. –

risposta

35

Quando ci si connette a un server SFTP ed è necessario connettersi alla cartella principale (ad esempio per leggere il contenuto della cartella) si otterrebbe comunque l'errore quando si utilizza solo "/" come percorso.

La soluzione che ho trovato era di usare il percorso "/./", che è un percorso valido che fa riferimento alla cartella radice. Ciò è utile quando l'utente con cui si effettua l'accesso ha accesso solo alla propria cartella principale e non è disponibile alcun percorso completo.

Quindi la richiesta al server quando si cerca di leggere il contenuto della cartella principale dovrebbe essere qualcosa di simile:

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

Questa è la risposta corretta. C'è stato un bug introdotto a partire da PHP 5.2 e 5.4 che ha interrotto l'accesso alla directory root. Grazie per aver fornito una soluzione! –

+2

Ho aggiunto un link alla tua risposta su https://bugs.php.net/bug.php?id=64169. –

+3

Siete i benvenuti @BradenAnderson, ho trovato così tante risposte qui che ho pensato di fornire quello che ho visto giusto –

8

Sto avendo un problema simile. Presumo che si sta facendo qualcosa di simile a questo:

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

Quando $remote_dir è il percorso completo dalla radice quindi open_dir opere. Se $remote_dir è solo '/' o '', allora ho l'errore 'impossibile aprire' come hai fatto tu.

Nel mio caso, sembra che ssh si connetta nella cartella radice anziché nella directory "home" come fa ftp. Hai detto che ha funzionato su un server diverso, quindi mi chiedo se è solo un problema di configurazione.

+1

Da quello che ho visto, hai ragione. Si connette alla directory radice piuttosto che a "casa". L'utilizzo del client sftp da riga di comando si connette a "home". Potrei semplicemente dover ottenere il percorso assoluto dal client a cui sto cercando di connettermi. –

+0

'$ dir = 'ssh2.sftp: //'.$sftp.'/'.$absolute_path;' L'uso del percorso assoluto al posto del percorso home è la risposta. – Aust

0

Recentemente ho trovato a SFTP su PHP di lavoro e ha scoperto che phpseclib era molto più facile da usare:

http://phpseclib.sourceforge.net/

Se hai il lusso di non essere su un host condiviso e possibile installare qualsiasi estensioni vuoi forse l'estensione PECL sarebbe meglio ma non tutti noi siamo così fortunati. Inoltre, l'API di phpseclib sembra un po 'più intuitiva, essendo OOP e tutto.

+0

valido solo per alcune versioni sftp, è indicato nei commenti delle librerie – Blacksonic

+1

Il 99% delle installazioni SFTP utilizza v3. In realtà, non ho mai incontrato un server SFTP che non lo supportava. Molti client supportano anche solo v3.WinSCP per esempio. Aggiungere supporto per v6 quando funziona v3 e quando nessuno usa nemmeno v6 sarebbe semplicemente uno spreco di risorse di sviluppo. –

+0

quindi sei fortunato, ma quando devi riscrivere le cose da perl a php per molti client, c'è sempre l'1% che usa la versione diversa – Blacksonic

1

Ho appena avuto lo stesso problema, ma ho potuto capire il problema.

Nel mio caso, quando mi collegavo al server, stavo andando alla radice dell'account e, a causa delle configurazioni del server, non ero in grado di scrivere lì.

Mi sono collegato all'account utilizzando un fireFTP e quindi ho potuto vedere dove si trovava la radice dell'account ... era la radice del server.

Ho dovuto includere l'intero percorso fino alla cartella in cui sono autorizzato a scrivere e quindi ho potuto risolvere il problema.

Quindi, il mio consiglio è di ottenere il percorso utilizzando un'interfaccia grafica (ho utilizzato fireFTP) e aggiungere l'intero percorso al codice.


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

Spero che questo possa aiutare te e altre persone con lo stesso problema!

Cheers!

+0

Questa è una buona idea. L'ho già provato utilizzando FireZilla e WinSCP. Ho usato quello che avevano come percorso assoluto senza successo, però. –

+0

C'è un modo per ottenere il vero percorso della home directory dell'utente? –

7

il modo più semplice per ottenere che SFTP funzioni in PHP (anche su Windows) senza installare alcuna estensione ecc. È PHPSECLIB: http://phpseclib.sourceforge.net/. Il materiale SSH è completamente implementato in una classe PHP.

si utilizza è così:

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

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

echo $sftp->pwd(); 
?> 
3

La documentazione su quella pagina contiene un errore. Date un'occhiata all'esempio qui: http://php.net/ssh2_sftp - ciò che dovete realmente fare è aprire una risorsa SFTP speciale usando ssh2_sftp() prima di usarlo con fopen(). E sì, sembra proprio così, ad es. "Risorsa # 24" quando convertito in stringa ... un po 'strano ma a quanto pare funziona.

Un'altra avvertenza è che SFTP viene avviato nella directory radice anziché nella directory principale dell'utente remoto, pertanto il percorso remoto nell'URI deve sempre essere assoluto.

0

Il mio problema era che mi stava collegando in funzione e tornare URL stringa con risorse all'interno . Una sfortunata risorsa è creata nel contesto della funzione e il garbage collector sta disconnettendo la risorsa alla fine della funzione. Soluzione: restituire la risorsa per riferimento e annullarla manualmente in un contesto più complesso.

13

Per le versioni di PHP> 5.6.27 uso 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

Questa è la risposta corretta! grazie. –

+0

In aumento, lo stesso qui. Immagino che PHP non capisca il suo tipo di dati nelle versioni più recenti. –

0

Ha risolto il problema attivando il supporto SFTP sul server (PowerShell)

Problemi correlati