T

PHP + ssh2

こちらに追記がある

大量のリモートサーバ上で何かの処理を一斉に実行したいとき、expect使ったりシェルで書くよりPHPに慣れた人ならPECLのssh2を使うと便利かも。

<?php

class sshClass {

    function __construct(){
        
    }
    
    function sshCls(){
        if(PHP_VERSION < 5){
            $this->__construct();
        }
    }
    
    function _setAuthPassword($user, $pass){
        if($user !== ''){
            $this->user = $user;
        }else{
            die("ユーザ名がありません。\\n");
        }
        
        if($pass !== ''){
            $this->pass = $pass;
        }else{
            die("パスワードがありません。\\n");
        }
    }
    
    function _connect($server){
        $this->conn = ssh2_connect($server, '22');
    }
    
    function execute($user, $pass, $server, $cmd){
        $this->_setAuthPassword($user, $pass);
        if($cmd === ''){
            die("コマンドを指定して下さい。\\n");
        }
        
        $cmd .= "\\n";
        
        $this->_connect($server);
        if(ssh2_auth_password($this->conn, $user, $pass)){
            //echo "Authentication Successful!\\n";
        }else{
            die("認証に失敗しました。\\n");
        }
        $fp = ssh2_shell($this->conn, 'xterm');
        
        if($fp){
            fwrite($fp, $cmd);
            //ココが肝心
            sleep(1);
            do{
                $data = fgets($fp, '1024');
                if(strlen($data) == 0){
                    break;
                }
                $this->return .= $data;
            }while(true);
        }else{
            die("接続に失敗しました。\\n");
        }
    }

    function getResult(){
        return $this->return;
    }
}

$obj = new sshClass();
$obj->execute('user', 'pass', 'example.com', "ls -l /home");
print($obj->getResult() . "\\n");

?>

こんな感じ。PECLモジュールのビルドにはlibssh2が必要。

それから、いろいろ試していたらscpでファイルの送信がうまくいかなかったので下のようにSFTPと組み合わせるメソッドを追加したり。

    function putFile($user, $pass, $server, $local, $remote, $perm='0644'){
        $this->_setAuthPassword($user, $pass);
        
        $this->_connect($server);
        if(ssh2_auth_password($this->conn, $user, $pass)){
            print("認証に成功しました。\\n");
        }else{
            die("認証に失敗しました。\\n");
        }

        if(ssh2_scp_send($this->conn, $local, $remote, $perm)){
            $this->return = "SCPでファイル".$local."を送信しました。\\n";
        }else{
            $this->return = "ファイルを送信できませんでした。SFTPに切り替えます。\\n";
            $this->sftp = ssh2_sftp($this->conn);
            $fp = fopen("ssh2.sftp://" . $this->sftp . $remote, 'w');
            if($fp){
                $data = file_get_contents($local);
                fwrite($fp, $data);
                fclose($fp);
                $this->return .= "SFTPでファイル".$local."を送信しました。\\n";
            }else{
                $this->return .= "ファイルを送信できませんでした。\\n";
            }
        }
    }

上の方、一度コマンド実行したら再接続しないといけないのでthis->connの使い回しはやめた。

Posted by on 7月 3, 2007 in PHP

コメントを残す