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
From:http://tw.wingwit.com/Article/program/PHP/201311/20797.html