samedi 27 juin 2009
Dans la journée d'hier, je travaillais sur une application PHP qui devait ouvrir une connexion SSH vers un serveur pour exécuter un script bash. En théorie, je devais simplement capturer le résultat en sortie du script appelé. Je m'en veux un peu car j'ai perdu un peu trop de temps à mon goût à essayer de figurer pourquoi il n'y avait aucun output. Pourtant, selon la documentation, ça semblait assez simple à réaliser. Et ça l'était une fois qu'on connaît les subtilités.
J'ai expérimenté avec les éléments suivants mais je n'ai retenu que la première solution :
- l'extension PHP Secure Shell 2 de PECL
- La classe SSH2 for PHP
- La librairie phpseclib qui contient Net_SSH2
- Un truc populaire que j'ai trouvé sur plusieurs forums (avec un shell)
La différence majeure est qu'en mode shell, l'environnement semble résoudre lui-même les chemins vers les programmes tandis qu'avec ssh2_exec, on doit spécifier les chemins absolus (la commande "whereis" devient alors très pratique pour les localiser). C'est exactement ce dont je n'ai pas eu le réflexe de tester.
Dans le code ci-dessous, une fois authentifié, il suffit d'indiquer le chemin complet de la commande à ssh2_exec().
// SSH : port 22 par défautLes deux dernières lignes permettent de récupérer le flux (stream) qui correspond uniquement au résultat de la commande (contrairement à ssh2_shell qui capture aussi le prompt). C'est beaucoup plus simple comme ça car sinon, avec le shell, on doit user d'ingéniosité en englobant la commande à l'intérieur de délimiteurs, attendre qu'elle s'exécute (l'utilisation de sleep peut s'avérer nécessaire pour patienter jusqu'à la fin de l'exécution du script), récupérer le texte qui s'est inscrit dans le terminal, extraire le flux de sortie en capturant ce qui se trouve entre les délimiteurs, nettoyer le tout et croiser les doigts pour que ça fonctionne bien à chaque fois.
$conn = ssh2_connect('ip', 22);
ssh2_auth_password($conn, 'username', 'password');
// Exemple 1 - output d'un script
$stream = ssh2_exec($conn, "/dir/get_movie_release_date.sh Gremlins", false);
// Exemple 2 - liste de fichiers
// $stream = ssh2_exec($conn, "/bin/ls ls -l /dir/", false);
// Exemple 3 - exit code d'un script bash
// $stream = ssh2_exec($conn, "/dir/routine.sh;echo $?;", false);
stream_set_blocking($stream, true);
echo stream_get_contents($stream);
En conclusion, trois points à retenir :
- ssh2_exec est plus fiable que ssh2_shell pour capturer le flux de sortie
- toujours spécifier le chemin complet menant aux commandes ou aux scripts à exécuter
- depuis la version 0.9, si on ne spécifie pas de pty, il faut ajouter "false" comme troisième argument de ssh2_exec(). Autrement, on obtient rien en sortie
Salut,
Serait-il possible de recupérer l'état d'une action, par exemple pour l'encodage, recupérer toutes les x secondes l'etat actuelle de l'encodage, en gros récupérer x seconde le résultat de la commande effectué car le probleme c'est que la page bloque, une fois fini sa affiche le résultat :s pas très utile malheureusement.
Avec SSH2, tu peux capturer l'output qui s'écrira dans un terminal suite à une commande. Qu'est-ce que ta commande doit récupérer comme information ?
Sinon, si tu as une opération qui demande à patienter et que tu souhaites vérifier l'état jusqu'à ce que le processus soit terminé, est-ce que APC ne serait pas plus approprié ?