zoukankan      html  css  js  c++  java
  • 利用ganymed-ssh2远程执行其它Linux机器上的shell命令

    实际应用中,有时候需要从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 即可 

      

  • 相关阅读:
    React Native学习(一)——搭建开发环境
    Linux 命令系列之 seq
    Linux 提高操作效率之 tab 命令补全
    Atlassian 系列软件安装(Crowd+JIRA+Confluence+Bitbucket+Bamboo)
    代码质量管理 SonarQube 系列之 安装
    kworkerds 挖矿木马简单分析及清理
    shell 脚本常用调试方法
    JVM 调优之 Eclipse 启动调优实战
    基于 Njmon + InfluxDB + Grafana 实现性能指标实时可视监控
    nmon 的下一代工具 njmon
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/4624204.html
Copyright © 2011-2022 走看看