利用ganymed-ssh2远程执行其它Linux机器上的shell命令

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

  

时间: 2024-10-13 03:58:48

利用ganymed-ssh2远程执行其它Linux机器上的shell命令的相关文章

linux远程通过shell脚本执行另一台linux机器上的shell文件

#!/bin/bash ssh root@192.168.1.102 << remotessh            #首先要ssh上去,ssh的配置可以看我的上一篇文章,注意这里的<< remotessh #从这里开始都是在远程机器上执行命令啦 cd /tmp/test/ rm -f test.txt cat test.log | grep 'test' >> test.txt echo "finished!" #执行完毕 exit  #不要忘记退

linux机器上部署多台Tomcat

在Linux机器上部署多台Tomcat, 我部署的是Tomcat8,只需要一步,即避免端口号冲突. 在解压后的tomcat目录下,修改conf下server.xml. 修改shutdown端口: <Server port="8050" shutdown="SHUTDOWN">//修改为没有被占用的端口 修改connector端口: <Connector port="9999" protocol="HTTP/1.1&qu

二十七、Linux下常用的shell命令记录

本文章记录我在linux系统下常用或有用的系统级命令,包括软硬件查看.修改命令,有CPU.内存.硬盘.网络.系统管理等命令.但本文不打算介绍生僻命令,也不介绍各个linux发行版下的特有命令,且以后会持续更新. 说明,我是在一个Centos 6.4 64位的虚拟机系统进行测试.本文介绍的命令都会在此Centos下运行验证(也有部分命令会在我的suse/ubuntu系统里测试的,会做特明说明),但运行结果就不再列出了. 硬件篇 CPU相关 lscpu #查看的是cpu的统计信息. cat /pro

Linux C/C++编程Shell命令大杂烩(1)

1, 查看发行版信息 cat /etc/issue 2, 查看内核版本 uname -r 查看内核版本 uname -p 查看处理器类型32bit/64bit uname -n 查看网络主机名(or hostname) 3,OpenJDK和JDK啥区别? Oracle JDK is based on the OpenJDK source code. In addition, it contains closed-source components. 也就是说,OpenJDK去掉了JDK中涉及一些

linux中新增一个shell命令的方法

1. 可以在一个自己建立的shell脚本中定义一个函数,使用 ". xxx.sh" 或者 "source xxx.sh" 运行这个shell脚本之后,其中的function就自动成为了当前shell中的新增命令了. 2. android编译配置环境时会运行. build/envsetup.sh脚本,就是使用这种方法为当前shell新增了一些命令,如:croot, lunch, mm, mmm, mma, cgrep等等.一直以为envsetup.sh中做了什么高级操

Ganymed SSH-2 java执行远程linux机器命令工具

Ganymed SSH2 for Java is a library which implements the SSH-2 protocol in pure Java(tested on J2SE 1.4.2 and 5.0). It allows one to connect to SSH servers from withinJava programs. It supports SSH sessions (remote command execution and shell access),

在 64 位 linux 机器上安装 jdk1.6 jdk-6u45-linux-x64.bin的安装

linux 平台上安装: 1.下载:jdk-6u45-linux-x64.bin 2.接下来,登录linux系统,赋予执行权限,命令如下: chmod +x jdk-6u21-linux-x64.bin 3.执行jdk的安装. ./jdk-6u45-linux-x64.bin 4.配置环境变量. 环境变量的配置分为几种方式,根据自己的选择配置: 方式一:在/etc/profile文件中配置JAVA_HOME以及PATH和CLASS_PATH 因为这样的设置将对所以用户的shell都生效,对系统安

直接在安装了redis的Linux机器上操作redis数据存储类型--对Sorted-Sets操作

一.概述: Sorted-Sets和Sets类型极为相似,它们都是字符串的集合,都不允许重复的成员出现在一个Set中.它们之间的主要差别是Sorted-Sets中的每一个成员都会有一个分数(score)与之关联,Redis正是通过分数来为集合中的成员进行从小到大的排序.然而需要额外指出的是,尽管Sorted-Sets中的成员必须是唯一的,但是分数(score)却是可以重复的. 在Sorted-Set中添加.删除或更新一个成员都是非常快速的操作,其时间复杂度为集合中成员数量的对数.由于Sorted

直接在安装了redis的Linux机器上操作redis数据存储类型--对key的操作

一.概述: 前几篇博客中,主要讲述的是与Redis数据类型相关的命令,如String.List.Set.Hashes和Sorted-Set.这些命令都具有一个共同点,即所有的操作都是针对与Key关联的Value的.而该篇博客将主要讲述与Key相关的Redis命令.学习这些命令对于学习Redis是非常重要的基础,也是能够充分挖掘Redis潜力的利器. 二.相关命令列表: 命令原型 时间复杂度 命令描述 返回值 KEYS pattern O(N) 时间复杂度中的N表示数据库中Key的数量.获取所有匹