Make SSH connections with PHP
Not everyone knows about PHP‘s capabilities of making SSH connections and executing remote commands, but it can be very useful. I’ve been using it a lot in PHP CLI applications that I run from cronjobs, but initially it was a pain to get it to work. The PHP manual on Secure Shell2 Functions is not very practicle or thorough for that matter, so I would like to share my knowledge in this how to, to make it a little less time consuming setting this up.
In this article I’m going to assume that:
- You’re running Debian / Ubuntu
If not, you will have to substitute the package manager aptitude with whatever your distribution provides - You’re running PHP 5
If not, just replace php5 with php4 everywhere - You have basic knowledge of PHP & server administration
- You already have PHP installed
Prerequisites
Packages
First let’s install the following packages:
sudo aptitude update
sudo aptitude install php5-dev php5-cli php-pear build-essential \
openssl-dev zlib1g-dev
That should set us up alright.
Update – On recent Ubuntu machines, there’s no need to do any compiling anymore:
aptitude install libssh2-1-dev
pecl install -f ssh2
echo 'extension=ssh2.so' > /etc/php5/conf.d/ssh2.ini
If the above works for you (you should see: "Build process completed successfully"), you can skip to Great! PHP supports SSH – time to code.
If not, you probably need to compile manually, continue reading here.
libssh2
We need libssh2 from sourcefourge. We have to compile this, but no worries, this is all you need to do:
cd /usr/src
wget http://surfnet.dl.sourceforge.net/sourceforge/libssh2/libssh2-0.14.tar.gz
tar -zxvf libssh2-0.14.tar.gz
cd libssh2-0.14/
./configure
make all install
That’s it! Easy right?
– Update: since December 26th 2008, libssh2 has reached version 1.0. Though I have not tested it: it has been reported to work. So you may want to check sf.net and download the latest stable version.
Installation
ssh2.so
Next we need to link libssh & PHP together. There’s a PECL module for this so let’s install using:
pecl install -f ssh2
The -f makes sure ssh2 is installed even though there’s not a stable candidate. You could also use the package name: ssh2-beta to overrule this.
Now you need to make sure our new ssh2.so module is loaded by PHP. Edit your php.ini file (for CLIApache utilities /etc/php5/apache2/php.ini)utitilies: /etc/php5/cli/php.ini, for
extension=ssh2.so
It should be placed beneath the: "Dynamic Extensions" section somewhere around line 515.
Great! PHP supports SSH – time to code
You’ve just enabled ssh2 support in PHP. Now how can we make use of this? There are 2 options. SSH supports the:
- execute method
This tells the server’s operating system to execute something and pipe the output back to your script. (recommended) - shell method
This opens an actual shell to the operating system, just as you would normally when logging in with your terminal application. Somerouters that don’t have a full POSIX compliant implementation, but run their own application as soon as you login, require this. (advanced)
Method 1: Execute
Best would be to create functions or even a class for the following code, but this is the basic idea and will definitely get you started:
if (!function_exists("ssh2_connect")) die("function ssh2_connect doesn't exist");
// log in at server1.example.com on port 22
if(!($con = ssh2_connect("server1.example.com", 22))){
echo "fail: unable to establish connection\n";
} else {
// try to authenticate with username root, password secretpassword
if(!ssh2_auth_password($con, "root", "secretpassword")) {
echo "fail: unable to authenticate\n";
} else {
// allright, we're in!
echo "okay: logged in...\n";
// execute a command
if(!($stream = ssh2_exec($con, "ls -al" )) ){
echo "fail: unable to execute command\n";
} else{
// collect returning data from command
stream_set_blocking( $stream, true );
$data = "";
while( $buf = fread($stream,4096) ){
$data .= $buf;
}
fclose($stream);
}
}
}
Method 2: Shell
Best would be to create functions or even a class for the following code, but this is the basic idea and will definitely get you started:
if (!function_exists("ssh2_connect")) die("function ssh2_connect doesn't exist");
// log in at server1.example.com on port 22
if(!($con = ssh2_connect("server1.example.com", 22))){
echo "fail: unable to establish connection\n";
} else {
// try to authenticate with username root, password secretpassword
if(!ssh2_auth_password($con, "root", "secretpassword")) {
echo "fail: unable to authenticate\n";
} else {
// allright, we're in!
echo "okay: logged in...\n";
// create a shell
if(!($shell = ssh2_shell($con, 'vt102', null, 80, 40, SSH2_TERM_UNIT_CHARS))){
echo "fail: unable to establish shell\n";
} else{
stream_set_blocking( $shell, true );
// send a command
fwrite($shell,"ls -al\n");
sleep(1);
// & collect returning data
$data = "";
while( $buf = fread($shell,4096) ){
$data .= $buf;
}
fclose($shell);
}
}
}
Tips
Sometimes when a server is busy, or a connection is buggy, the buffer may run dry, and the PHP script stops collecting data from a command output (even though the command hasn’t completed yet!). There are a couple of things you could do about that:
ssh2_exec($con, 'ls -al; echo "__COMMAND_FINISHED__"' );
Now, in the loop where you keep checking for the buffer, just see if the COMMAND_FINISHED line is coming by. Because then you know you have all the data. To avoid infinite loops, just limit the loop with a timeout of 10 seconds or so:
$time_start = time();
$data = "";
while( true ){
$data .= fread($stream, 4096);
if(strpos($data,"__COMMAND_FINISHED__") !== false){
echo "okay: command finished\n";
break;
}
if( (time()-$time_start) > 10 ){
echo "fail: timeout of 10 seconds has been reached\n";
break;
}
}
In the example above, you’d better set stream_set_blocking to false.
Can’t get enough?
PHP can send files over ssh!
ssh2_scp_send($con, "/tmp/source.dat", "/tmp/dest.dat", 0644);
Doesn’t work?
Check the following:
– Did you follow every step of the prerequisites & installation how to in this article?
– On the serverside, ‘PasswordAuthentication yes’ must be enabled in the sshd_config. Default is yes on most servers, but in some cases you will have to turn this on yourself by making sure the following lines are in place in the file: /etc/ssh/sshd_config:
# Change to yes to enable tunnelled clear text passwords
PasswordAuthentication yes
If you’ve made any changes, ssh needs a restart
/etc/init.d/ssh restart
中文操作方法:
首先,系统需要已经装有openssl和openssl-devel包
rpm -qa | grep openssl
然后,安装libssh2
当下来源代码后
./configure && make all install
再然后,安装PECL/ssh2
可以用命令pear install ssh2(眼前可能只能用pear install ssh2-beta)
或者是去PECL/ssh2当下来源代码
然后
phpize && ./configure –with-ssh2 && make
再然后把生成的ssh2.so文件拷贝到php.ini中申明的extension_dir目录下(这里是/usr/lib/php4)
cp modules/ssh2.so /usr/lib/php4/
再在/etc/php.d目录下新建一个文件ssh2.ini
echo “extension=ssh2.so” > /etc/php.d/ssh2.ini
再重起web server,让其重读php.ini
搞定