`

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

 
阅读更多
Java SSH远程执行Shell脚本实现
此程序需要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。
分享到:
评论
4 楼 无心流泪wan 2015-08-28  
19774279 写道
内容其实不错,但是还是希望楼主给出原文地址或者是稍微排个版,代码看起来真的是比较混乱。


http://www.blogjava.net/jnbzwm/archive/2010/09/26/332944.html
3 楼 19774279 2015-01-15  
内容其实不错,但是还是希望楼主给出原文地址或者是稍微排个版,代码看起来真的是比较混乱。
2 楼 zhangxing89757 2014-07-17  
请问下如何调用perl脚本啊?我用这个能够调用perl脚本,但是执行到perl脚本里面perl自带的方法后就不在往下执行了!!!
1 楼 di1984HIT 2013-12-13  
鞋的很好啊,学习了。

相关推荐

    (接上篇博客)Java SSH远程执行Shell脚本实现

    NULL 博文链接:https://killeraction.iteye.com/blog/1022141

    Java实现windows下远程调用shell脚本

    该工具是基于SSH2协议的实现,在使用它的过程中非常容易,只需要指定合法的用户名口令,或者授权认证文件,就可以创建到远程Linux主机的连接,在建立起来的会话中调用该Linux主机上的脚本文件,执行相关操作。

    远程shell调用.rar

    本人根据实际项目需求所开发的,SSH2远程执行Linux中Shell脚本Java小工具,亲测有效!里赋有已打好的程序jar包及工具使用说明,简单易用,很方便哟!

    java程序里实现ssh, scp, sftp

    在java里可以通过Ganymed SSH-2, Expect4j等实现ssh登录,由于Ganymed SSH-2是纯java实现,并且可以实现scp,sftp等,因此我们采用Ganymed SSH-2 1&gt; 下载安装 从http://code.google.com/p/ganymed-ssh-2/ 下载...

    Java 调用 Linux shell 命令执行框架:sshxcute

    sshxcute 就是这样一个框架工具集,它基于 JSCH 构建,允许工程师利用Java 代码通过 SSH 连接远程批量执行 Linux/UNIX 系统上的命令或者脚本,同时加入了判断成功与否,取回输出等多种实用功能。sshxcute 不管是针对...

    Jsch批量执行多条命令,包含切换用户输入密码

    参考expect4j的交互式操作方式控制输入输出流实现批量执行多条shell命令同时支持切换用户输入密码提权执行命令输入密码等操作 有完整的测试用例,便于理解 模板化执行命令示例 [$]send[su - root] [Password:]...

    ganymed-ssh2-build

    ganymed-ssh2-build210.jiar包与源码 Java通过SSH2协议执行远程Shell脚本(ganymed-ssh2-build210.jar)

    shell-exec-java-server

    shell-exec-java-server描述使用这个服务器,你可以访问远程服务器并执行shell命令例如)你会丢失ssh密钥,但不要担心。 保持此服务器正常工作意味着您有后门。用法第一步更改运行此程序的端口。 public static ...

    shell-script-connector:与IBM Integration bus配合使用的连接器和节点,可从本地或远程(ssh)Shell中的消息流执行命令行脚本

    外壳脚本连接器 与IBM Integration bus配合使用的连接器和节点,用于从本地或远程(ssh)Shell中的消息流执行命令行脚本。

    JAVA上百实例源码以及开源项目

    百度云盘分享 ... Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText();...

    java开源包4

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    JAVA上百实例源码以及开源项目源代码

     Java实现的FTP连接与数据浏览程序,实现实例化可操作的窗口。  部分源代码摘录:  ftpClient = new FtpClient(); //实例化FtpClient对象  String serverAddr=jtfServer.getText(); //得到服务器地址  ...

    java开源包3

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包11

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包6

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包101

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包9

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包5

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包8

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

    java开源包10

    ftp4j是一个FTP客户端Java类库,实现了FTP客户端应具有的大部分功能文件(包括上传和下 载),浏览远程FTP服务器上的目录和文件,创建、删除、重命,移动远程目录和文件。ftp4j提供多种方式连接到远程FTP服务器包括...

Global site tag (gtag.js) - Google Analytics