Transfert SFTP en PHP fonction ssh2_sftp

#1
Bonjour,

j'avais un cron qui fonctionnait bien depuis pas mal de mois pour le transfert d'un fichier texte journalier. D'un seul coup j'ai une erreur systématique sur la fonction:

$sftpStream = @fopen($sftpUrl, 'w');

avec $sftpUrl="ssh2.sftp://Resource id #10/transferts/2017-01-09_14-20_export.csv"

L'administrateur du serveur cible me précise qu'il n'y eu aucune modification de leur config. Est-ce que cela pourrait provenir d'une mise à jour de PHP ou toute mise à jour liée au protocole de communication SFTP sur la plateforme PH ?

A noter que Resource id #10 est un cast string du retour de la fonction: resource ssh2_sftp ( resource $session )

référence code source utilisé:
http://php.net/ssh2_sftp

extrait source:

Code:
   if (!function_exists("ssh2_connect"))
    {
        write_file($log,"function ssh2_connect doesn't exist",true);
        fclose($log);
        die();
    }
    $connection = ssh2_connect($ftp_host, 22);
    if(!$connection)
    { // connexion
        write_file($log,"La connexion ssh2_connect $ftp_host a echoue.",true);
        fclose($log);
        die();
    }
    if (!ssh2_auth_password($connection, $ftp_user_name, $ftp_user_pass))
    { // identification
        write_file($log,"La connexion ssh2_auth_password $ftp_host a echoue. user:$ftp_user_name pass:$ftp_user_pass",true);
        fclose($log);
        ssh2_exec($connection, 'exit');
        die();
    }
 
    $sftp        = @ssh2_sftp($connection); // initialise un sous-systeme SFTP
    if (!$sftp)
       throw new Exception("erreur sur initialisation sous-systeme SFTP");

        $target_file = $target_path . $target_file;
        $sftpUrl     = "ssh2.sftp://".$sftp.$target_file;
    $sftpStream  = @fopen($sftpUrl, 'w');   // creation flux pour fichier cible
 
    if (!$sftpStream)
       throw new Exception("erreur sur creation ficher cible: $sftpUrl");
 
Dernière édition par un modérateur:

PH-Quentin

Administrator
Membre du personnel
#2
Bonjour MarcMarin,

Merci pour votre message, êtes-vous certain que "Resource id #10" est bien un string et non un objet contenant une erreur ? Avez-vous tenté en hardcodant l'host SFTP?

Pourriez-vous SVP activer l'affichage des erreurs dans votre script PHP afin que nous soyons en mesure de diagnostiquer la cause du problème ? Pour ce faire, il suffit de rajouter ces deux lignes de code en dessous de la valide PHP à savoir "<?php"

Code:
error_reporting( E_ALL );
@ini_set( 'display_errors', 1 );
Une fois ces deux lignes rajoutées, je vous invite à lancer votre code et nous indiquer le message d'erreur retourné !

J'attends votre retour (d'erreur) !
Quentin
 
#3
Bonjour et merci Quentin pour votre implication sur cette problématique.

alors en hardcodant la fonction sous la forme:

PHP:
ssh2.sftp://user:pass@example.com:22/path/to/filename
çà marche ! ;-) ce qui veut donc dire que la fonction

PHP:
$sftp = @ssh2_sftp($connection)
ne renvoie pas false mais un 'Resource id #10'

Alors que la connexion en amont se passe bien.
PHP:
$connection = ssh2_connect($ftp_host, 22);
if(!$connection)
...
if (!ssh2_auth_password($connection, $ftp_user_name, $ftp_user_pass))
...
finalement pourquoi passer par ces 3 dernières fonctions alors qu’apparemment on peut directement passer tous les paramètres par ssh2.sftp

Certains d'ailleurs se posent la question sur Resource id #10 ici:

http://stackoverflow.com/questions/1466737/cant-get-sftp-to-work-in-php

Concernant le log des erreurs error_reporting(E_ALL ) puisque la fin de la ligne de commande du cron contient >/dev/null 2>&1
comment la rediriger vers un log ? j'ai essayé de remplacer /dev/null par /logs/syslog.log (puique l'espace dispose déjà d'un répertoire logs)
Quel est la bonne pratique ?

merci d'avance
 
Dernière édition par un modérateur:

PH-Quentin

Administrator
Membre du personnel
#5
Bonjour et merci Quentin pour votre implication sur cette problématique.

alors en hardcodant la fonction sous la forme:

ssh2.sftp://user:pass@example.com:22/path/to/filename

çà marche ! ;-) ce qui veut donc dire que la fonction
$sftp = @ssh2_sftp($connection)
ne renvoie pas false mais un 'Resource id #10'

Alors que la connexion en amont se passe bien.
$connection = ssh2_connect($ftp_host, 22);
if(!$connection)
...
if (!ssh2_auth_password($connection, $ftp_user_name, $ftp_user_pass))
...

finalement pourquoi passer par ces 3 dernières fonctions alors qu’apparemment on peut directement passer tous les paramètres par ssh2.sftp

Certains d'ailleurs se posent la question sur Resource id #10 ici:

http://stackoverflow.com/questions/1466737/cant-get-sftp-to-work-in-php

Concernant le log des erreurs error_reporting(E_ALL ) puisque la fin de la ligne de commande du cron contient >/dev/null 2>&1
comment la rediriger vers un log ? j'ai essayé de remplacer /dev/null par /logs/syslog.log (puique l'espace dispose déjà d'un répertoire logs)
Quel est la bonne pratique ?

merci d'avance
Rebonjour,

Je suis content d'apprendre que nous avançons dans le debug du code !

Lorsque que je regarde la documentation de PHP.net, je constate que la valeur de retour de la fonction ssh2_sftp n'est pas un booléen mais bien une ressource !

Cependant un peu plus bas dans les exemples nous pouvons effectivement voir ce code qui permet de vérifier si la connexion SFTP à eu lieu avec succès ou pas:



Après il faut bien comprendre que dans cette variable vous n'avez pas le hostname/chemin du serveur mais bien une ressource de connexion, si vous souhaitez donc initialiser une connexion avec fopen, d'après mon expérience il va falloir ré-indiquer le hostname/nom du fichier à atteindre en utilisant une autre variable de type string.

Vous pouvez pas exemple voir le type d'une variable PHP en utilisant gettype comme ceci:

Code:
echo gettype($sftp), "<br>\n";
Bien à vous,
Quentin
 
#6
je suis bien d'accord avec vous Quentin, cette construction de fonction fopen est bien curieuse

PHP:
$sftp = ssh2_sftp($connection);
$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'w');
d'autant plus qu'on la retrouve dans plein de documents PHP y compris dans votre lien:

Code:
$stream = @fopen("ssh2.sftp://$sftp$remote_file", 'w')
et de plus elle m'avait pas posé de problème à moi et à d'autres.

donc puisqu'il suffit de remplacer par une string du user/hostname, c'est ce que je vais faire et au diable les complications ! ;-)

Merci en tout cas.
 
Dernière édition par un modérateur:

olidev

New Member
#7
For this, you will first have to create PHP SFTP connection. This can be done by using sftp library called PHPseclib. This library is really easy to install if you have ssh access on the server. You can use phpseclib to directly upload and download files from ftp.
 
Haut