SSH可以通过将联机的封包加密的技术进行资料的传递; 使用SSH可以把传输的所有数据进行加密即使有人截获到数据也无法得到有用的信息同时数据经过压缩大大地加快了传输的速度总之通过SSH的使用可以确保资料传输比较安全并且传输效率较高
不过并非所有人知道PHP可以与SSH连接的特性以及与执行远程命令的能力不过这方面却非常有用由于我们可以在很多不同的方面利用PHP因此它有很多设置选项来控制其行为一组庞大的可选参数能够保证您可以将 PHP 用于许多不同的目的但这同时也意味着这些参数和服务端配置的组合会带来一些安全问题笔者一直在PHP CLI应用程序中使用SSH笔者是从cronjobs中使用它的不过一开始并非十分简单可以说颇费周折关于安全使用Shell 函数的手册也不是十分实用笔者进行了多次试验之后才有了今天这篇小文章愿您读了之后能为您配置PHP节省一点儿时间
在这篇文章中笔者需要假设
你正在运行的操作系统是Debian / Ubuntu如果你运行的不是Debian / Ubuntu你可能需要用你的Linux发行版本提供的数据包管理器来替换本文对应内容
你运行的是PHP如果你运行的不是PHP可用PHP代替之
你对PHP和服务器管理有基本的了解
你已经安装了PHP
先决条件
安装程序包
首先让我们安装下面的程序包
sudo aptitude update
sudo aptitude install phpdev phpcli phppear buidessential \
openssldev zlibgdev
安装完成进入下一步
编译libssh
在从sourceforge网站下载了Libssh之后我们需要编译它不过不要担心你只需要按照如下的方法操作
cd /usr/src
wget surfne/sourceforge/libssh/libsshtargz
tar zxvf libsshtargz
cd libssh/
/configure
make all install
如果你想检查是否有了一个新版本可以查看SFNET不过这个版本就足够了
安装
安装sshso
下一步我们需要将libssh和 PHPr链接起来有一个PECL模块可以完成这个功能我们可以使用PEAR安装它
pear install f ssh
f参数确保SSH被安装即使并没有一个稳定的选择对象你还可以使用如下的包名称sshbeta来强行运行
现在你需要确保我们这个新的SSHSO模块被PHP加载编辑你的phpini文件(对于CLI实用程序/etc/php/cli/phpini对于Apache实用程序/etc/php/apache/phpini)
extension=sshso
这应该放在Dynamic Extensions的下面大约在第行左右
PHP支持SSH编写代码
你刚刚在PHP中启用了SSH那么现在应该如何利用它呢?有两个选择SSH支持
执行方法
这告诉你的服务器的操作系统来执行什么东西并且通过管道传回到你的脚本
外壳方法
这种方法在操作系统中打开一个实际的外壳这正像通过终端应用程序登录时所操作的那样有一些路由器并没有一个完全的POSIX一致性实施过程而是在你登录时立即运行其自身的应用程序这时你就需要这种方法
下面我们分别详述之
第一种方法执行
你最好为下面的代码创建函数或者是一个类不过本文仅仅起到一个为您提供基本观念的作用所以说你可以如此开始
if (!function_exists(ssh_connect)) die(function ssh_connect doesnt exist)
// log in at on port
if(!($con = ssh_connect( ))){
echo fail: unable to establish connection\n;
} else {
// try to authenticate with username root password secretpassword
if(!ssh_auth_password($con root secretpassword)) {
echo fail: unable to authenticate\n;
} else {
// allright were in!
echo okay: logged in\n;
// execute a command
if(!($stream = ssh_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) ){
$data = $buf;
}
fclose($stream);
}
}
第二种方法外壳
同样道理你也可以为如下的代码编写函数或者一个类不过本文仅仅提供基本观念
if (!function_exists(ssh_connect)) die(function ssh_connect doesnt exist)
// log in at on port
if(!($con = ssh_connect( ))){
echo fail: unable to establish connection\n;
} else {
// try to authenticate with username root password secretpassword
if(!ssh_auth_password($con root secretpassword)) {
echo fail: unable to authenticate\n;
} else {
// allright were in!
echo okay: logged in\n;
// create a shell
if(!($shell = ssh_shell($con vt null SSH_TERM_UNIT_CHARS))){
echo fail: unable to establish shell\n;
} else{
stream_set_blocking( $shell true );
// send a command
fwrite($shellls al\n);
sleep();
// & collect returning data
$data = ;
while( $buf = fread($shell) ){
$data = $buf;
}
fclose($shell);
}
}
}
小提示
有时服务器忙碌或者一个连接出错缓沖区没有数据PHP脚本就会停止从一个命令输出(即使命令并没有完成!)中收集数据你可以为此进行如下的操作
ssh_exec($con ls al; echo __COMMAND_FINISHED__ );
现在在你不断地检查缓沖区的循环中只需要看一下COMMAND_FINISHED因为你就可以知道你拥有了所有的数据为了避免无限循环(死循环)可以用一个秒的超时限制
$time_start = time();
$data = ;
while( true ){
$data = fread($stream );
if(strpos($data__COMMAND_FINISHED__) !== false){
echo okay: command finished\n;
break;
}
if( (time()$time_start) > ){
echo fail: timeout of seconds has been reached\n;
break;
}
}
在上面的例子中你最好将stream_set_blocking设为false
通过SSH发送文件
ssh_scp_send($con /tmp/sourcedat /tmp/destdat );
如果不能正常工作
请检查如下的几个方面
依照本文检查你操作的每一步
在服务器端在sshd_config 中必须启用PasswordAuthentication yes在大多数服务器上默认值是yes不过有些情况下你可能需要将下面的一行加入到文件中即亲自动手打开这个功能
/etc/ssh/sshd_config:
# Change to yes to enable tunnelled clear text passwords
PasswordAuthentication yes
如果作了改变就需要重新启动SSH
/etc/initd/ssh restart