Action:
<?php include('Net/SSH2.php'); include('File/ANSI.php'); define('NET_SSH2_LOGGING', NET_SSH2_LOG_COMPLEX); $ssh = new Net_SSH2('www.domain.tld'); if (!$ssh->login('username', 'password')) { exit('Login Failed'); } // save $ssh->getServerPublicHostKey() if this is your first time connecting // check $ssh->getServerPublicHostKey() against previously saved value on subsequent connections echo $ssh->exec('pwd'); echo $ssh->exec('ls -la');echo $ssh->exec('pwd'); // outputs /home/username $ssh->exec('cd /'); echo $ssh->exec('pwd'); // (despite the previous command) outputs /home/usernameecho $ssh->read('username@username:~$'); $ssh->write("ls -la\n"); // note the "\n" echo $ssh->read('username@username:~$');echo $ssh->read('username@username:~$'); $ssh->write("sudo ls -la\n"); $output = $ssh->read('#[pP]assword[^:]*:|username@username:~\$#', NET_SSH2_READ_REGEX); echo $output; if (preg_match('#[pP]assword[^:]*:#', $output)) { $ssh->write("password\n"); echo $ssh->read('username@username:~$'); }$ssh->setTimeout(1); echo $ssh->read();function packet_handler($str) { echo $str; } $ssh->exec('ping 127.0.0.1', 'packet_handler');$ansi = new File_ANSI(); $ansi->appendString($ssh->read('username@username:~$')); $ssh->write("top\n"); $ssh->setTimeout(5); $ansi->appendString($ssh->read()); echo $ansi->getScreen(); // outputs HTML$ssh->setTimeout(2); $ssh->read(); $ssh->write("vim\n"); $ssh->read(); $ssh->write("\x1BOP"); // send F1 $ansi = new File_ANSI(); $ansi->appendString($ssh->read()); echo $ansi->getScreen(); echo $ssh->getLog(); ?>
By default $ssh->exec()
returns both stdout and stderr. To suppress stderr you can call $ssh->enableQuietMode()
. To re-enable it call $ssh->disableQuietMode()
.
To get stderr separately from stdout you'll need to call $ssh->enableQuietMode()
and then call $ssh->getStdError()
. These functions work with $ssh->read()
as well.
To get the exit status you can call $ssh->getExitStatus()
If done on an interactive shell, the output you'd receive for the first pwd would (depending on how your system is setup) be different than the output of the second pwd. The above code snippet, however, will yield two identical lines.
The reason for this is that any "state changes" you make to the one-time shell are gone once the exec() has been ran and the channel has been deleted.
You can workaround this on Linux by doing $ssh->exec('cd /; pwd')
After each $ssh->read()
the timeout resets to what you set it to last. By default the "channel" remains open so if you do $ssh->write("ping 127.0.0.1\n")
and do two successive $ssh->read()
you'll get ping output in both of those calls. If you don't want it to do that you can either send Ctrl + C via $ssh->write("\x03")
or you can reset the whole channel by calling $ssh->reset()
.
$ssh->isTimeout()
will return true if the result of the last $ssh->read()
or $ssh->exec()
was due to a timeout. Otherwise it will return false.
$ssh->setTimeout()
works with $ssh->read()
and $ssh->exec()
.
On a terminal you normally don't just type the command and expect to get the output. You type the command and then hit enter. To simulate that you'll need to add "\n"
to the commands you send via write()
By default, sudo caches passwords for 5 minutes after they've been entered. So while $ssh->read('Password:')
will work the first time you try it, it won't work if you try it within a five minutes after having initially ran it.
This example is best run via the CLI. Run it via the webbrowser and you may need to flush the output buffer and even then YMMV.
Some commands issued to a terminal may yield ANSI escape codes. eg. ^[[H
. These provide the terminal with information on the formating of the characters and their positioning.
Since Net_SSH2 uses vt100 as the "TERM environment variable value" a VT100 terminal emulator is needed to properly handle the ANSI escape codes. File_ANSI aims to be such an emulator. The default screen size is 80x24.
$ansi->getScreen()
returns what'd be seen on the current screen. In the case of top this is desirable as it'll produce output like this:
top - 23:39:24 up 77 days, 1:13, 1 user, load average: 0.00, 0.00, 0.00
Tasks: 45 total, 2 running, 43 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1740956k total, 1079288k used, 661668k free, 221240k buffers
Swap: 0k total, 0k used, 0k free, 399940k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 16 0 2128 696 600 S 0.0 0.0 0:01.10 init
2 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
3 root 34 19 0 0 0 S 0.0 0.0 0:00.05 ksoftirqd/0
4 root RT 0 0 0 0 S 0.0 0.0 0:00.01 watchdog/0
5 root 10 -5 0 0 0 S 0.0 0.0 0:00.25 events/0
6 root 11 -5 0 0 0 S 0.0 0.0 0:00.63 khelper
7 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 kthread
8 root 14 -5 0 0 0 S 0.0 0.0 0:00.00 xenwatch
9 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 xenbus
17 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 kblockd/0
46 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 aio/0
45 root 15 0 0 0 0 S 0.0 0.0 0:00.64 kswapd0
562 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 kseriod
657 root 15 0 0 0 0 S 0.0 0.0 0:04.23 kjournald
718 root 13 -4 2360 656 424 S 0.0 0.0 0:00.18 udevd
1592 root 14 -2 2396 848 560 S 0.0 0.0 0:00.03 dhclient
1647 root 15 0 0 0 0 S 0.0 0.0 0:00.16 kjournald
In the case of ls, however, it is less desirable. For commands like ls it may be preferable to do $ansi->getHistory()
. For top, that'd return the following:
__| __|_ ) Fedora 8
_| ( / 32-bit
___|\___|___|
Welcome to an EC2 Public Image
:-)
Base
--[ see /etc/ec2/release-notes ]--
[username@username:~$]$top
top - 23:51:56 up 77 days, 1:25, 1 user, load average: 0.00, 0.00, 0.00
Tasks: 45 total, 2 running, 43 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 1740956k total, 1079256k used, 661700k free, 221240k buffers
Swap: 0k total, 0k used, 0k free, 399940k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 16 0 2128 696 600 S 0.0 0.0 0:01.10 init
2 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
3 root 34 19 0 0 0 S 0.0 0.0 0:00.05 ksoftirqd/0
4 root RT 0 0 0 0 S 0.0 0.0 0:00.01 watchdog/0
5 root 10 -5 0 0 0 S 0.0 0.0 0:00.25 events/0
6 root 11 -5 0 0 0 S 0.0 0.0 0:00.63 khelper
7 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 kthread
8 root 14 -5 0 0 0 S 0.0 0.0 0:00.00 xenwatch
9 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 xenbus
17 root 10 -5 0 0 0 S 0.0 0.0 0:00.00 kblockd/0
46 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 aio/0
45 root 15 0 0 0 0 S 0.0 0.0 0:00.64 kswapd0
562 root 20 -5 0 0 0 S 0.0 0.0 0:00.00 kseriod
657 root 15 0 0 0 0 S 0.0 0.0 0:04.23 kjournald
718 root 13 -4 2360 656 424 S 0.0 0.0 0:00.18 udevd
1592 root 14 -2 2396 848 560 S 0.0 0.0 0:00.03 dhclient
1647 root 15 0 0 0 0 S 0.0 0.0 0:00.16 kjournald
The history, by default, stores 200 lines (not including the current screen). Both functions return HTML with the various formatting properties specified by HTML. If you don't want HTML and want just the raw text of the terminal without any formatting do htmlspecialchars_decode(strip_tags($ansi->getScreen()))
.
A table of special characters and the keys they correspond to can be found at SSH2 Special Characters. The output of the above program is as follows:
*help.txt* For Vim version 7.3. Last change: 2010 Jul 20 VIM - main help file k Move around: Use the cursor keys, or "h" to go left, h l "j" to go down, "k" to go up, "l" to go right. j Close this window: Use ":q<Enter>". Get out of Vim: Use ":qa!<Enter>" (careful, all changes are lost!). Jump to a subject: Position the cursor on a tag (e.g. |bars|) and hit CTRL-]. With the mouse: ":set mouse=a" to enable the mouse (in xterm or GUI). Double-click the left mouse button on a tag, e.g. |bars|. Jump back: Type CTRL-T or CTRL-O (repeat to go further back). Get specific help: It is possible to go directly to whatever you want help on, by giving an argument to the |:help| command. It is possible to further specify the context: *help-context* WHAT PREPEND EXAMPLE ~ Normal mode command (nothing) :help x help.txt [Help][RO] 1,1 Top [No Name] 0,0-1 All "help.txt" [readonly] 221L, 8239C
The output may look different than vim when ran through, for example, PuTTY, because PuTTY uses xterm
as it's shell whereas phpseclib uses vt100
.