Java SSH远程执行Shell脚本实现(转)

摘要:
前言本程序需要ganymed-ssh2-build210.jar包(下载地址:http://www.ganymed.ethz.ch/ssh2/)为了调试方便,可以直接将ganymed-ssh2-build210src下的代码复制到项目中。此源代码的优点是它不依赖于许多其他包,并且可以干净地复制。介绍的目的是在远程机器上执行shell脚本;远程计算机IP:****************用户名:sshapp密码

前言

此程序需要ganymed-ssh2-build210.jar包(下载地址:http://www.ganymed.ethz.ch/ssh2/)
为了调试方便,可以将ganymed-ssh2-build210src下的代码直接拷贝到工程里,
此源码的好处就是没有依赖很多其他的包,拷贝过来干干净净.

简介

目的:是执行远程机器上的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-build210examples下的例子吧。

转自:http://rainyear.iteye.com/blog/1339825

免责声明:文章转载自《Java SSH远程执行Shell脚本实现(转)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇kibana软件具体参数配置信息Camera2必知必会下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Java引用总结--StrongReference、SoftReference、WeakReference、PhantomReference

Java引用总结--StrongReference、SoftReference、WeakReference、PhantomReference   1 Java引用介绍   Java从1.2版本开始引入了4种引用,这4种引用的级别由高到低依次为:    强引用  >  软引用  >  弱引用  >  虚引用 ⑴强引用(StrongRefe...

Java导出CSV文件

阅读原文 调用类 @Test public void testWrite() throws Exception { FileOutputStream fos = new FileOutputStream("E:/cjsworkspace/cjs-excel-demo/target/abc.csv"); OutputS...

C#正则表达式匹配“换行\回车”等问题

C# 正则表达式 换行\回车 问题 string s = "......."; string r = @"(?s)(?i)导演:\s*</span>\s*<span\s+class=""m_c"">\s*<span& gt;<a.*?>(?<director>.*?)</a>"; s...

web优化之js动态合并 动态压缩 去掉js重复引用 js缓存 js延迟加载

做web前段也有一段时间了,对于web中js文件的加载有些体会想跟大家一起分享一下。 1.首先说说js文件的合并和压缩吧 为了便于集中式管理js的合并和压缩我们创建一个Js.ashx文件来专门处理合并压缩,这里我们借用Yahoo.Yui.Compressor工具来压缩我们的js文件 代码如下: public classJs : IHttpHandler...

Java:String和Date、Timestamp之间的转换

一、String与Date(java.util.Date)互转      1.1 String -> Date String dateStr = "2010/05/04 12:34:23";            Date date = new Date();            //注意format的格式要与日期String的格式相匹配  ...

程序自动更新版本

增加了程序自动更新版本的功能,实现方式如下: 后台数据库中用一张表来保存程序的版本信息,该表的字段很简单,如下: CREATE TABLE [dbo].[sys_AutoUpdate]( [UID] [int] IDENTITY(1,1) NOT NULL, [SystemName] [varchar](50) NULL, [SystemVers...