标签:
实际应用中,有时候需要从web管理界面上,远程去启动其它linux主机上的程序,利用ssh协议可以方便的满足这一需求。事实上hadoop架构中,从nn上启动dn时,就是利用了这一原理。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:
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 即可
利用ganymed-ssh2远程执行其它Linux机器上的shell命令
标签:
原文地址:http://www.cnblogs.com/yjmyzz/p/4624204.html