博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java SSH远程执行Shell脚本实现
阅读量:4053 次
发布时间:2019-05-25

本文共 5445 字,大约阅读时间需要 18 分钟。


此程序需要ganymed-ssh2-build210.jar包。 

下载地址:http://www.ganymed.ethz.ch/ssh2/ 

为了调试方便,可以将\ganymed-ssh2-build210\src下的代码直接拷贝到我们的工程里, 

此源码的好处就是没有依赖很多其他的包,拷贝过来干干净净。 


此程序的目的是执行远程机器上的Shell脚本。 

远程机器IP:***.**.**.*** 

用户名:sshapp 

密码:sshapp 

登录后用pwd命令,显示当前目录为:/sshapp. 

在/sshapp/myshell/目录下有myTest.sh文件,内容如下: 

echo $1 $2 $# 

#print $1 

我们的Java代码RmtShellExecutor.java: 

/** *//** 

* 远程执行shell脚本类 

* @author l 

*/ 

public class RmtShellExecutor { 

    

    /** *//**  */ 

    private Connection conn; 

    /** *//** 远程机器IP */ 

    private String     ip; 

    /** *//** 用户名 */ 

    private String     usr; 

    /** *//** 密码 */ 

    private String     psword; 

    private String     charset = Charset.defaultCharset().toString(); 


    private static final int TIME_OUT = 1000 * 5 * 60; 


    /** *//** 

     * 构造函数 

     * @param param 传入参数Bean 一些属性的getter setter 实现略 

     */ 

    public RmtShellExecutor(ShellParam param) { 

        this.ip = param.getIp(); 

        this.usr = param.getUsername(); 

        this.psword = param.getPassword(); 

    } 


    /** *//** 

     * 构造函数 

     * @param ip 

     * @param usr 

     * @param ps 

     */ 

    public RmtShellExecutor(String ip, String usr, String ps) { 

        this.ip = ip; 

        this.usr = usr; 

        this.psword = ps; 

    } 


    /** *//** 

     * 登录 

     * 

     * @return 

     * @throws IOException 

     */ 

    private boolean login() throws IOException { 

        conn = new Connection(ip); 

        conn.connect(); 

        return conn.authenticateWithPassword(usr, psword); 

    } 


    /** *//** 

     * 执行脚本 

     * 

     * @param cmds 

     * @return 

     * @throws Exception 

     */ 

    public int exec(String cmds) throws Exception { 

        InputStream stdOut = null; 

        InputStream stdErr = null; 

        String outStr = ""; 

        String outErr = ""; 

        int ret = -1; 

        try { 

            if (login()) { 

                // Open a new {@link Session} on this connection 

                Session session = conn.openSession(); 

                // Execute a command on the remote machine. 

                session.execCommand(cmds); 

                

                stdOut = new StreamGobbler(session.getStdout()); 

                outStr = processStream(stdOut, charset); 

                

                stdErr = new StreamGobbler(session.getStderr()); 

                outErr = processStream(stdErr, charset); 

                

                session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT); 

                

                System.out.println("outStr=" + outStr); 

                System.out.println("outErr=" + outErr); 

                

                ret = session.getExitStatus(); 

            } else { 

                throw new AppException("登录远程机器失败" + ip); // 自定义异常类 实现略 

            } 

        } finally { 

            if (conn != null) { 

                conn.close(); 

            } 

            IOUtils.closeQuietly(stdOut); 

            IOUtils.closeQuietly(stdErr); 

        } 

        return ret; 

    } 


    /** *//** 

     * @param in 

     * @param charset 

     * @return 

     * @throws IOException 

     * @throws UnsupportedEncodingException 

     */ 

    private String processStream(InputStream in, String charset) throws Exception { 

        byte[] buf = new byte[1024]; 

        StringBuilder sb = new StringBuilder(); 

        while (in.read(buf) != -1) { 

            sb.append(new String(buf, charset)); 

        } 

        return sb.toString(); 

    } 


    public static void main(String args[]) throws Exception { 

        RmtShellExecutor exe = new RmtShellExecutor("***.**.**.***", "sshapp", "sshapp"); 

        // 执行myTest.sh 参数为java Know dummy 

        System.out.println(exe.exec("sh /webapp/myshell/myTest.sh java Know dummy")); 

//        exe.exec("uname -a && date && uptime && who"); 

    } 


执行后结果: 

outStr=java Know 3 

outErr= 

0 // getExitStatus方法的返回值 

注:一般情况下shell脚本正常执行完毕,getExitStatus方法返回0。 

此方法通过远程命令取得Exit Code/status。但并不是每个server设计时都会返回这个值,如果没有则会返回null。 

在调用getExitStatus时,要先调用WaitForCondition方法,通过ChannelCondition.java接口的定义可以看到每个条件的具体含义。见以下代码: 

ChannelCondition.java 

package ch.ethz.ssh2; 


/** *//** 

* Contains constants that can be used to specify what conditions to wait for on 

* a SSH-2 channel (e.g., represented by a {@link Session}). 


* @see Session#waitForCondition(int, long) 


* @author Christian Plattner, plattner@inf.ethz.ch 

* @version $Id: ChannelCondition.java,v 1.6 2006/08/11 12:24:00 cplattne Exp $ 

*/ 


public abstract interface ChannelCondition 


    /** *//** 

     * A timeout has occurred, none of your requested conditions is fulfilled. 

     * However, other conditions may be true - therefore, NEVER use the "==" 

     * operator to test for this (or any other) condition. Always use 

     * something like <code>((cond & ChannelCondition.CLOSED) != 0)</code>. 

     */ 

    public static final int TIMEOUT = 1; 


    /** *//** 

     * The underlying SSH-2 channel, however not necessarily the whole connection, 

     * has been closed. This implies <code>EOF</code>. Note that there may still 

     * be unread stdout or stderr data in the local window, i.e, <code>STDOUT_DATA</code> 

     * or/and <code>STDERR_DATA</code> may be set at the same time. 

     */ 

    public static final int CLOSED = 2; 


    /** *//** 

     * There is stdout data available that is ready to be consumed. 

     */ 

    public static final int STDOUT_DATA = 4; 


    /** *//** 

     * There is stderr data available that is ready to be consumed. 

     */ 

    public static final int STDERR_DATA = 8; 


    /** *//** 

     * EOF on has been reached, no more _new_ stdout or stderr data will arrive 

     * from the remote server. However, there may be unread stdout or stderr 

     * data, i.e, <code>STDOUT_DATA</code> or/and <code>STDERR_DATA</code> 

     * may be set at the same time. 

     */ 

    public static final int EOF = 16; 


    /** *//** 

     * The exit status of the remote process is available. 

     * Some servers never send the exist status, or occasionally "forget" to do so. 

     */ 

    public static final int EXIT_STATUS = 32; 


    /** *//** 

     * The exit signal of the remote process is available. 

     */ 

    public static final int EXIT_SIGNAL = 64; 



当我们把myTest.sh修改为如下内容: 

echo $1 $2 $# 

print $1由于我使用的linux机器上没有print命令,所以print $1会报错:command not found。 


接下来再让我们执行一下,看看控制台的结果: 

outStr=java Know 3 

outErr=/sshapp/myshell/myTest.sh: line 2: print: command not found 

127 

此时shell脚本出现错误,getExitStatus方法返回127. 


在实际应用中,可以将outStr和outErr记录到日志中,以便维护人员查看shell的执行情况, 

而getExitStatus的返回值,可以认为是此次执行是否OK的标准。 


其他代码请看\ganymed-ssh2-build210\examples\下的例子吧。 


本文为原创,欢迎转载,转载请注明出处BlogJava。
你可能感兴趣的文章
linux kconfig配置
查看>>
linux不同模块completion通信
查看>>
linux printf获得时间戳
查看>>
C语言位扩展
查看>>
linux irqdebug
查看>>
git 常用命令
查看>>
linux位操作API
查看>>
uboot.lds文件分析
查看>>
uboot start.s文件分析
查看>>
没有路由器的情况下,开发板,虚拟机Ubuntu,win10主机,三者也可以ping通
查看>>
本地服务方式搭建etcd集群
查看>>
安装k8s Master高可用集群
查看>>
忽略图片透明区域的事件(Flex)
查看>>
忽略图片透明区域的事件(Flex)
查看>>
AS3 Flex基础知识100条
查看>>
Flex动态获取flash资源库文件
查看>>
01Java基础语法-16. while循环结构
查看>>
01Java基础语法-18. 各种循环语句的区别和应用场景
查看>>
01Java基础语法-19. 循环跳转控制语句
查看>>
Django框架全面讲解 -- Form
查看>>