雖然現今大部分的網路設備都提供了親切的WEB介面讓管理人員能夠快速的完成設定,但是如果遇到了需要批次且大量的設定狀況,對於程式來說,WEB介面就顯得相當的難以整合,因此,若要批次完成某些設定,文字介面(Command Line Interface, CLI),依然是兼顧效能與開發方便的首選,不過,若使用傳統Telnet方式進行設定,難免存在著網路竊聽的風險,加密的連線設定方式當然因應而生,而SSH則是目前相當普遍的網路設備遠端設定方式。
問題來了,該如何開發一個WEB Base的整合性網管介面能讓此系統管理大量的網路設備呢?透過SNMP當然是種選擇,對於一般網路管理者來說,CLI應是再熟悉不過的工具,所以若能讓網頁程式利用加密連線來集中控管,也是不錯的選擇。
最近公司剛好遇到這樣的問題,雖然開發程式的不是我,不過對於網頁程式該如何用SSH連接網路設備我倒是滿有興趣的,總不會笨到還要透過網頁程式去call另外模組(maybe是C、C++或者perl)處理吧?上網找看看PHP有沒有支援SSH,果然,PHP有支援SSH2ㄟ....不過這個模組不是預設的,如果要使用要另外做些設定,因為在公司不像在學校,要幾台機器有幾台,所以只有Win32的環境可以測試,下面是我的測試心得。
關於PHP對SSH的支援請見官方網站
安裝:
在PHP SSH2 manual的安裝教學裡面,告訴我們如果在Win32的環境下要使用PHP的SSH2模組必須要到http://snaps.php.net去下載php_ssh2.dll這個dll檔案,但是奇妙的是,snaps.php.net沒有這個下載點阿?原來,這個外掛的dll是放在pecl-版本-dev.zip中。
你可以根據你的php版本下載相對應的檔案回來,解壓縮後,照著installation manual的方法把他擺在extension diretory裡面,像我把PHP裝在C:\php\下面,而把extension放在php預設的extension directory "C:\php\ext\"裡面,接著修改php.ini,這邊要注意php.ini裡面extension_dir這個變數所指的是哪裡,我的php.ini裡面預設是"./",如果不修改這個設定的話,php_ssh2.dll就必須要擺在你的php根目錄下(像是我的環境就是C:\php\)。
在官方的Installation manaul中的範例是將檔案放在C:\php5\exts中,並修改php.ini裡面extension_dir這個參數,這邊請根據個人喜好安裝,接著就是在php.ini裡面加上一行啟用這個extension的設定:extension=php_ssh2.dll,修改完php.ini後,電腦裡面PHP對SSH2的支援設定就算完成了。
程式:
在官方網站中有網友分享了他寫的class,經過我的修改後如下:
我修改的部份主要是新增了一個getResult的function,這個function是提供writeShell()寫入命令後,Server回傳的response,另外把cmdExec()這個function裡面的fread換成stream_get_contents(),最主要是因為我沒辦法control主機回傳stream的大小,所以利用stream_get_contents(),當然,用fgets()也是可以的,這兩個function哪一個處理的效率比較好在PHP官網上面有人比較過,不過我忘記誰比較快了。
值得注意的是,ssh2_exec()一次只能執行一個指令,也就是說,在執行完ssh2_exec()之後,PHP就會將連線中斷,下一個ssh2_exec()執行時,會重新Login進去執行,也就是說指令之間是不會有關聯性的,這對網路設備來說是非常不合理的,因為有用過網路設備的都知道,要完成一項作業可能會需要很多道指令,每個指令可能都有階層式關係,我目前的解法是在每個指令後用換行符號接起來,eg."config firewall policy \n edit 1\n"。
由於上面的原因,所以在大部分情況下,用ssh2_shell()是比較好的解決方式,不過因為ssh2_shell()不會主動中斷連線,使用時(Class裡面的openShell跟writeShell),記得要把logout的指令一並執行,不然程式會hang住(感謝小王子學長幫我debug)。
範例一:
使用ssh2_exec()連線
範例二:
使用ssh2_shell()連線
如Alvin所問的連續登入,只需要按照一般登入登出動作依序執行即可,如下面範例, 批次大量的執行可以考慮寫成function再加上multi-process來做:
問題來了,該如何開發一個WEB Base的整合性網管介面能讓此系統管理大量的網路設備呢?透過SNMP當然是種選擇,對於一般網路管理者來說,CLI應是再熟悉不過的工具,所以若能讓網頁程式利用加密連線來集中控管,也是不錯的選擇。
最近公司剛好遇到這樣的問題,雖然開發程式的不是我,不過對於網頁程式該如何用SSH連接網路設備我倒是滿有興趣的,總不會笨到還要透過網頁程式去call另外模組(maybe是C、C++或者perl)處理吧?上網找看看PHP有沒有支援SSH,果然,PHP有支援SSH2ㄟ....不過這個模組不是預設的,如果要使用要另外做些設定,因為在公司不像在學校,要幾台機器有幾台,所以只有Win32的環境可以測試,下面是我的測試心得。
關於PHP對SSH的支援請見官方網站
安裝:
在PHP SSH2 manual的安裝教學裡面,告訴我們如果在Win32的環境下要使用PHP的SSH2模組必須要到http://snaps.php.net去下載php_ssh2.dll這個dll檔案,但是奇妙的是,snaps.php.net沒有這個下載點阿?原來,這個外掛的dll是放在pecl-版本-dev.zip中。
你可以根據你的php版本下載相對應的檔案回來,解壓縮後,照著installation manual的方法把他擺在extension diretory裡面,像我把PHP裝在C:\php\下面,而把extension放在php預設的extension directory "C:\php\ext\"裡面,接著修改php.ini,這邊要注意php.ini裡面extension_dir這個變數所指的是哪裡,我的php.ini裡面預設是"./",如果不修改這個設定的話,php_ssh2.dll就必須要擺在你的php根目錄下(像是我的環境就是C:\php\)。
在官方的Installation manaul中的範例是將檔案放在C:\php5\exts中,並修改php.ini裡面extension_dir這個參數,這邊請根據個人喜好安裝,接著就是在php.ini裡面加上一行啟用這個extension的設定:extension=php_ssh2.dll,修改完php.ini後,電腦裡面PHP對SSH2的支援設定就算完成了。
程式:
在官方網站中有網友分享了他寫的class,經過我的修改後如下:
| <?php // ssh protocols // note: once openShell method is used, cmdExec does not work class ssh2 { private $host = 'host'; private $user = 'user'; private $port = '22'; private $password = 'password'; private $con = null; private $shell_type = 'xterm'; private $shell = null; private $log = ''; function __construct($host='', $port='' ) { if( $host!='' ) $this->host = $host; if( $port!='' ) $this->port = $port; $this->con = ssh2_connect($this->host, $this->port); if( !$this->con ) { $this->log .= "Connection failed !"; } } function authPassword( $user = '', $password = '' ) { if( $user!='' ) $this->user = $user; if( $password!='' ) $this->password = $password; if( !ssh2_auth_password( $this->con, $this->user, $this->password ) ) { $this->log .= "Authorization failed !"; } } function openShell( $shell_type = '' ) { if ( $shell_type != '' ) $this->shell_type = $shell_type; $this->shell = ssh2_shell( $this->con, $this->shell_type ); if( !$this->shell ) $this->log .= " Shell connection failed !"; stream_set_blocking( $this->shell, true ); } function writeShell( $command = '' ) { fwrite($this->shell, $command."\n"); } function cmdExec( ) { $argc = func_num_args(); $argv = func_get_args(); $cmd = ''; for( $i=0; $i<$argc ; $i++) { if( $i != ($argc-1) ) { $cmd .= $argv[$i]." && "; }else{ $cmd .= $argv[$i]; } } echo $cmd; $stream = ssh2_exec( $this->con, $cmd ); stream_set_blocking( $stream, true ); return stream_get_contents($stream); } function getLog() { return $this->log; } function getResult(){ $contents=''; while (!feof($this->shell)) { $contents.=fgets($this->shell); } return $contents; } } ?> |
值得注意的是,ssh2_exec()一次只能執行一個指令,也就是說,在執行完ssh2_exec()之後,PHP就會將連線中斷,下一個ssh2_exec()執行時,會重新Login進去執行,也就是說指令之間是不會有關聯性的,這對網路設備來說是非常不合理的,因為有用過網路設備的都知道,要完成一項作業可能會需要很多道指令,每個指令可能都有階層式關係,我目前的解法是在每個指令後用換行符號接起來,eg."config firewall policy \n edit 1\n"。
由於上面的原因,所以在大部分情況下,用ssh2_shell()是比較好的解決方式,不過因為ssh2_shell()不會主動中斷連線,使用時(Class裡面的openShell跟writeShell),記得要把logout的指令一並執行,不然程式會hang住(感謝小王子學長幫我debug)。
範例一:
使用ssh2_exec()連線
| <? //將上面的class檔include進來 include_once("ssh2.php"); //初始化class $shell = new ssh2("設備IP"); $shell->authPassword("帳號","密碼"); //執行指令 $result=$shell->cmdExec("指令"); //印出指令執行結果 echo $result; ?> |
使用ssh2_shell()連線
| <? //將上面的class檔include進來 include_once("ssh2.php"); //初始化class $shell = new ssh2("設備IP"); $shell->authPassword("帳號","密碼"); //設定Terminal Type,預設就是xterm $shell->openShell("xterm"); //執行指令 $shell->writeShell("指令1"); $shell->writeShell("指令2"); //登出logout指令(譬如在linux就是exit) $shell->writeShell("logout"); //得到執行結果 $result=$shell->getResult(); //印出指令執行結果 echo $result; ?> |
如Alvin所問的連續登入,只需要按照一般登入登出動作依序執行即可,如下面範例, 批次大量的執行可以考慮寫成function再加上multi-process來做:
| <? //將上面的class檔include進來 include_once("ssh2.php"); //************************** * 登入第一台設備 ***************************// //初始化class $shell = new ssh2("設備IP"); $shell->authPassword("帳號","密碼"); //設定Terminal Type,預設就是xterm $shell->openShell("xterm"); //執行指令 $shell->writeShell("指令1"); $shell->writeShell("指令2"); //登出logout指令(譬如在linux就是exit) $shell->writeShell("exit"); //得到執行結果 $result=$shell->getResult(); //印出指令執行結果 echo $result; //************************** * 登入第二台設備 ***************************// //初始化class $shell = new ssh2("設備IP"); $shell->authPassword("帳號","密碼"); //設定Terminal Type,預設就是xterm $shell->openShell("xterm"); //執行指令 $shell->writeShell("指令1"); $shell->writeShell("指令2"); //登出logout指令(譬如在linux就是exit) $shell->writeShell("exit"); //得到執行結果 $result=$shell->getResult(); //印出指令執行結果 echo $result; ?> |
文章標籤
全站熱搜

請問如果是用了ssh_shell, 可以怎樣把connection 中斷? 因為想在同一個程式中分別連上1台ssh, 中斷, 再連到第2台ssh. 謝謝
目前手邊沒設備可以測試,不過應該直覺是執行完logout指令後(像Linux上面就是exit),接著重複做登入動作即可,下禮拜上班後測試有心得再放上來。
我的環境是Windows Xp + appserv--2.6版 我有下載到php6的php_ssh2.dll這個檔案。 也把它照你所說的方法把它掛起來..但是不知道為什麼...還是一直出現以下這個錯誤訊息... Fatal error: Call to undefined function ssh2_connect()
通常出現Call to undefined function主要是php.ini裡面沒有把extension開啟,可能要檢查一下你系統Default使用的php.ini(用phpinfo()可以查到你php是使用哪一個php.ini)裡面是不是有加上extension=php_ssh2.dll這行,再不然就可能是php6裡面這個function的名字有改變。 php官方網站上的php6還沒正式release,建議還是用php5會比較保險一點(沒想到appserv的php版本跑的這麼快)。
^^感謝您 我已經可以使用了。我改用PHP 5了。
不好意思..再問一個問題。 就是呀,我如果寫一個shell script。 例如:xxx.sh 他主要執行之後會list工作清單,然後再詢問,要執行哪項工作事項。 然後我輸入選項代號之後。 他又會要求我輸入帳號 再要求我輸入密碼 之後才會真正的完成。 那如果我使用ssh2_shell() 他能夠正常執行嗎@@?
不好意思..上面的之後完成前面應該還有動作。 就是輸入完密碼之後,程式會去run一小段時間,因為它會跟好幾台主機連線作業。 打完密碼,真正作業完時間大約二十秒內。 那如果我直接php的ssh2_shell() 直接如下這樣寫.. $shell->writeshell("sh xx.sh"); $shell->writeshell("工作編號"); $shell->writeshell("帳號"); $shell->writeshell("密碼"); $shell->writeshell("exit"); 這樣寫會不會有問題ㄚ??
這個你可能要弄個環境來試試,就目前用的感覺,我覺得應該沒有問題
感謝, 今天使用了一下 ====================安裝過程==================== // Ubuntu 8.04.3 LTS // PHP 5 (cli) # apt-get install php5-dev p hp5-cli php-pear build-essential libssl-dev zlib1g-dev # wget http://downloads.sourceforge.net/project/libssh2/libssh2-1.2.1.tar.gz?use_mirror=ncu # tar zxf libssh2-1.2.1.tar.gz # cd libssh2-1.2.1/ # ./configure ; make ; make install # pecl install -f ssh2 // 如果編譯不過可能要更新 libssh2 http://sourceforge.net/projects/libssh2/files/ # echo 'extension=ssh2.so' >> /etc/php5/cli/php.ini ================================================ ====================新增了方法==================== // 為了可以讓本機 root 使用 public key 來驗證登入遠端執行命令 // key 的產生與複製到遠端可以參考 OpenSSH Public Key Authentication function authRootPublicKey( $user = '' ) { if( !ssh2_auth_pubkey_file( $this->con, $this->user, "/root/.ssh/id_rsa.pub", "/root/.ssh/id_rsa", 'secret') ) { $this->log .= "Authorization failed !"; } } ================================================
cool~感謝分享阿....
請問 "php_ssh2.dll" 要去哪download ? 是不是指 "php-5.2-dev (tar.gz)"這個檔,但解壓縮之後沒有看到 php_ssh2.dll ? 安裝環境: WinXP (32bit) ; apache 2.0.45 ; php5.2.12
PHP官網上面已經不提供pecl的extension binary了,有需要的話可以到http://pecl.php.net/package/ssh2下載原始碼來編譯,如果會用pecl的話可以試著裝裝看,我在windows上面用pecl裝extension一次都沒有成功過,如果裝成功的話,也請網路上的高手分享一下?感恩啦
我想請問一下 我按照上面的方式做完 因該是連線成功了但是我想要做的是windows php遠端去linux下指令 但利用上面的程式碼並沒有執行請問有其他的指令能執行嗎?
我想請問一下,就是我這裡需要連綫到一個server去做刪除檔案的動作。 當我key linux指令后,他會跳出一行確認,如:“Are You Sure? (Y or N)” 就是還要再打一個"Y",它才能刪除。請問您有任何方法解決這個問題嗎? 謝謝!