Live stream d’une console SSH en PHP
J’ai récemment eu le besoin de créer un stream live entre une application PHP et un serveur debian via SSH2 dans lequel une commande tail -f est lancée, cette commande permet de récupérer immédiatement dans le flux de sorti les modifications apportées au fichier, notamment les nouvelles lignes.
Pour ce faire, c’est très simple me direz-vous, on ouvre une connexion SSH2, on exécute la commande et on attend les résultats dans le flux, oui mais il faut faire ça proprement et de manière coordonnée.
Pour établir une connexion SSH, il existe nativement des fonctions ssh2_* dans PHP qui viennent avec la lib php5-ssh2, j’ai développé une classe qui utilise ses fonctions de manière à interagir avec un objet plutôt qu’une ressource, le but n’étant pas ici de vous montrer comment utiliser cette classe, je passerai sur sa configuration, si vous avez des questions, n’hésitez pas à commenter.
Pour ce faire, d’abord, on configure PHP.
1 2 3 4 |
ignore_user_abort(true);// Ignorer la déconnexion de l'utilisateur set_time_limit(0);// Aucune limite d'exécution ini_set('default_socket_timeout', 3600);// Timeout des sockets session_write_close();// Déverrouille la session |
On récupère ensuite notre flux de données en SSH.
1 2 3 4 5 |
$ssh = new SSH2($host, $port, $knownFingerprint); // Définir l'authentification $stream = $ssh->execRaw('tail -n 100 -f /path/to/output.log'); stream_set_blocking($stream, false); |
Le flux ne doit surtout pas être bloquant si vous souhaitez qu’il continue lorsque votre utilisateur se déconnecte.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
do { $line = fgets($stream); if( $line ) { // $line contient la ligne actuelle // Faites ici ce dont vous avez besoin echo $lines."<br>"; } else { // On met en pause pour alléger le serveur usleep(200);// Dormir 200ms // On ne flush rien si rien n'est envoyé au client echo "\x00"; } // Pour utiliser connection_aborted(), il faut flush() avant, // le statut de la connexion n'est actualisé que dans ce cas. flush(); } while( !connection_aborted() ); |
Il est important de laisser notre serveur souffler un peu alors si la ligne est vide, on le laisse dormir un peu.
Ici, on s’arrête proprement si l’utilisateur s’est déconnecté, d’où l’utilisation de connection_aborted().
Enfin, on ferme proprement notre flux et sa connexion SSH2.
1 2 |
fclose($stream); $ssh2->disconnect(); |
Ainsi le processus web se termine, la connexion SSH est fermée et le processus sur notre serveur SSH s’est arrêté.
Ma bibliothèque SSH2 : Voir sur GitHub