文章出處

實際應用中,有時候需要從web管理界面上,遠程去啟動其它linux主機上的程序,利用ssh協議可以方便的滿足這一需求。事實上hadoop架構中,從nn上啟動dn時,就是利用了免密碼ssh登錄。ganymed-ssh2是一個實現了ssh協議的開源項目,項目地址為:http://ganymed-ssh-2.googlecode.com/ (下載源碼要翻強,眾所周知的原因),如果只是使用的話,pom.xml添加以下依賴項就行了:

1         <dependency>
2             <groupId>ch.ethz.ganymed</groupId>
3             <artifactId>ganymed-ssh2</artifactId>
4             <version>262</version>
5         </dependency>

為了方便起見,封裝了一個工具類SSHUtil.java(已托管在taobao.org上)

package com.cnblogs.yjmyzz.utils;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * SSH工具類(可遠程執行其它Linux機器上的Shell命令)
 * Created by jimmy on 2015/7/6.
 * http://code.taobao.org/p/y-lib/src/trunk/src/main/java/com/cnblogs/yjmyzz/utils/SSHUtil.java
 */
public class SSHUtil {

    /**
     * 連接到主機
     *
     * @param hostname
     * @param username
     * @param password
     * @return
     * @throws Exception
     */
    private static Connection getConnection(String hostname, String username, String password) throws Exception {
        Connection conn = null;
        try {
            conn = new Connection(hostname);
            conn.connect();
            boolean isAuthenticated = conn.authenticateWithPassword(username, password);
            if (isAuthenticated == false) {
                throw new IOException("Authentication failed.");
            }
        } catch (Exception e) {
            throw new IOException("username or password error.");
        }
        return conn;
    }


    /**
     * 執行遠程命令
     *
     * @param hostname 遠程主機IP
     * @param username 用戶名
     * @param password 密碼
     * @param command  需要執行的命令
     * @param timeout  超時時間(秒)
     * @return
     * @throws Exception
     */
    public static String execRemoteCommand(String hostname, String username, String password, String command, long timeout)
            throws Exception {
        Connection conn = getConnection(hostname, username, password);
        StringBuilder sb = new StringBuilder();
        Session session = null;
        try {
            session = conn.openSession();
            session.requestPTY("vt100", 80, 24, 640, 480, null);
            session.execCommand(command);
            InputStream stdout = new StreamGobbler(session.getStdout());
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
            long start = System.currentTimeMillis();
            char[] arr = new char[512];
            int read;
            int i = 0;
            while (true) {
                read = br.read(arr, 0, arr.length);
                if (read < 0 || (System.currentTimeMillis() - start) > timeout * 1000) {
                    break;
                }
                sb.append(new String(arr, 0, read));
                i++;
            }
        } finally {
            if (session != null) {
                session.close();
            }
            if (conn != null) {
                conn.close();
            }
        }
        return sb.toString();
    }


    /**
     * 執行遠程命令(默認5秒超時)
     *
     * @param hostname 遠程主機IP
     * @param username 用戶名
     * @param password 密碼
     * @param command  需要執行的命令
     * @return
     * @throws Exception
     */
    public static String execRemoteCommand(String hostname, String username, String password, String command)
            throws Exception {
        return execRemoteCommand(hostname, username, password, command, 5);
    }


    /**
     * 批量執行遠程命令
     *
     * @param hostname 遠程主機IP
     * @param username 用戶名
     * @param password 密碼
     * @param command  需要執行的命令列表
     * @param timeout  超時時間(秒)
     * @return
     * @throws Exception
     */
    public static String execRemoteCommand(String hostname, String username, String password, String[] command, long timeout)
            throws Exception {
        Connection conn = getConnection(hostname, username, password);
        StringBuilder sb = new StringBuilder();
        Session session = null;
        try {
            for (int t = 0; t < command.length; t++) {
                session = conn.openSession();
                session.requestPTY("vt100", 80, 24, 640, 480, null);
                session.execCommand(command[t]);
                InputStream stdout = new StreamGobbler(session.getStdout());
                BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
                long start = System.currentTimeMillis();
                char[] arr = new char[512];
                int read;
                int i = 0;
                while (true) {
                    read = br.read(arr, 0, arr.length);
                    if (read < 0 || (System.currentTimeMillis() - start) > timeout * 1000) {
                        break;
                    }
                    sb.append(new String(arr, 0, read));
                    i++;
                }
                session.close();
            }
        } finally {
            if (conn != null) {
                conn.close();
            }
        }
        return sb.toString();
    }

    /**
     * 批量執行遠程命令(默認5秒超時)
     *
     * @param hostname 遠程主機IP
     * @param username 用戶名
     * @param password 密碼
     * @param command  需要執行的命令列表
     * @return
     * @throws Exception
     */
    public static String execRemoteCommand(String hostname, String username, String password, String[] command)
            throws Exception {
        return execRemoteCommand(hostname, username, password, command, 5);
    }
}

使用要點:

1. 如果要連續執行多個命令,用&&連接,比如:先 cd / 切換到根目錄,然后再ls 根目錄下的所有文件,可以這樣調用:

    public static void main(String[] args) {
        String hostname = "172.21.129.**";
        String username = "root";
        String password = "***";
        try {
            System.out.println(SSHUtil.execRemoteCommand(hostname, username, password,
                    "pwd&&cd /&&pwd&&ls"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

上面的命令相當于在同一個session下,連續執行

pwd

cd /

pwd

ls

2. 如果要以后臺進程調用命令,傳入命令時,直接加 nohup 即可 

  


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


全站熱搜
創作者介紹
創作者 大師兄 的頭像
大師兄

IT工程師數位筆記本

大師兄 發表在 痞客邦 留言(0) 人氣()