Using PHP ssh2 lib to create simple SSH client with ANSI support
If you’re a real geek, you might want to make an ssh client… using php, well, this is something that no one will probably ever need to do… but if you’re reading this, maybe it happens so that you need it
So, to start with, there is a php extension called libssh2, and it’s really tricky to install it on some server configurations. I’m not going to discuss that part here because it’s purely server administration issue. I will just get to the coding part.
What we want to do here is to create php script that would run from console, will connect to remote ssh server, execute commands, and display output just like every ssh client does. The first problem is – libssh2 documentation on php site really sucks.
Connecting to remote server is easy:
$connection = ssh2_connect($host, 22); ssh2_auth_password($connection, $user, $password); $stream = ssh2_shell($connection);
What you do here is basically connect to remote server, and fetch a stream from ssh2_shell function which you will use to do IO operations.
Now here comes the tricky part, according to the manual, the way you do an output to ssh (like execute a command) is to call ssh2_exec function, but this doesn’t really work well. When you do output using that command, your ssh stream gets reset, and you can’t just continue writing new commands that will work based on previous command. It’s like this – you cant do a “cd” command and then “ls”, cause “ls” will show contents of folder that was shown before you did “cd” (the logged in users home folder). Anyway here is the way I solved it:
You can use simple fwrite() function to work with your $stream variable, like this
fwrite($stream, $command."\n");
Now getting to the fetching output part, it might sound weird but don’t use fread() here
To get the server’s output you should use stream_get_contents function instead of fread. If you do – it works perfectly. Just keep in mind that server output will not appear immediately, you need to wait for it (do a loop).
So this is nearly all you need to know to setup and maintain a simple ssh2 connection, execute commands, and get output in one session.
Here are some other aspects you might have problems with:
First of all, the obvious one, what if you typed a command like ping or top or something that is going to end only if you press, the Ctr+C keys? the way to imitate the Ctr+C combination is pretty easy, this combination actually sends a signal to the system that’s terminating the current process, and it’s just….. number 3 character in ASCII table (Bingo!
)
It’s one of so called ETX signals (like end of text)
fwrite($stream, chr(3));
You do this command, and ping or top or whatever it is – terminates.
Next thing, I want to tell you is that in ANSI terminal there is not only text, you can have Midnight Commander ( mc ) which is nice and coloured, and htop and lot’s of others, how does that work?
Very simple! There’s an ANSI mode for terminal which is getting some other types of signals, like not only text but “go to next line” or “set foreground colour to green” e.g. I’m not going to go through the aspects of ANSI terminal, I will just explain how to enable it on libssh2 because by default it is using simple text mode and output of htop command will be more than weird.
And again it’s not explained in the manual in any imaginable way, but here is how you do it:
$stream = ssh2_shell($connection, 'ansi');
PHP Manual says that it’s possible to give the ANSI parameter to ssh2_exec, but in our case we do not use it (we had problems with the library when trying to implement this) so it appears, through not discussed in manual, that you can pass that parameter to ssh2_shell function as well and when using that stream you will get output in “ANSI” way. You just need to make sure you parse it correctly and display to end user as it’s supposed to be.
So that’s mainly it about creating this stuff using PHP, feel free to ask if you had any issues, or discovered some other methods

Sounds almost like the interactiveRead() / interactiveWrite() examples mentioned in the phpseclib documentation:
http://phpseclib.sourceforge.net/documentation/net.html#net_ssh_ssh1
@Sadie
Well, not exactly, see, if you use interactiveRead/Write you will have some problems determining if Output is done or not, and as they say:
interactiveRead() / interactiveWrite() are not implemented in Net_SSH2. The SSH-2 protocol supports them, however, phpseclib does not.
“Well, not exactly, see, if you use interactiveRead/Write you will have some problems determining if Output is done or not”
I don’t think you can do that with PECL’s ssh2 extension, either. As you note, “you need to wait for [the output] (do a loop)”. How long do you wait in the loop for? And after the output has concluded how do you know that the output is finished? What if you’re running a program that pauses for ten seconds and your loop only lasts for one second? You might think the output is done even though it isn’t.
Besides, a loop should work with phpseclib, too. Do the loop and then concatenate to a string until the output of interactiveRead() is empty, at which point, you can assume you’re done.
That said, in my own tests, one problem with both interactiveRead() and ssh2_shell() is this: you’ll get banner messages with it whereas you don’t with ssh2_exec() / phpseclib’s exec().
Nifty little article, I wonder if you could expand a bit on the thing you mention about “server output will not appear immediately, you need to wait for it (do a loop)”.
I’m struggling with how exactly to loop. In fact I can only get things working by doing a sleep(3) or what-have-you, clearly not somehting I want to keep.
:-/
Hi David, by saying loop I meant to put your stream_get_contents part in while loop, with sleep 1 second. (that’s how I did that) and that’s probably the only way, you can’t put handler on this, and clearly php is not the best language to do this kind of operation, but if you stuck with php it’s the only way. Surely that loop can be done in some thread or something, so you can do other operations while you wait for output to come.
Hi CyberJoe, simply a good article. Could you write a same article using phpseclib if you have tried?
And for the above article could you write an example script on how did you use stream_get_contents to get the server’s output as what David was referring. Thank you.