码迷,mamicode.com
首页 > 其他好文 > 详细

Ganymed SSH-2

时间:2015-09-29 00:00:25      阅读:367      评论:0      收藏:0      [点我收藏+]

标签:

    我们在日常开发中,有时候会遇到触发一个linux命令,比如清理临时文件,或者触发一个shell命令。那么这个时候就需要通过java去调用shell命令。 这里我们使用java自带的ProcessBuilder 来完成任务。ProcessBuilder类是用于创建操作系统进程。通过本机远程ssh到另外一台机器上去执行shell命令的需求,这种使用方式经常用于一台机器集群管理其他机器的需求。

    java里可以通过Ganymed SSH-2, Expect4j等实现ssh登录,基步骤如下:

一、下载安装

http://www.ganymed.ethz.ch/ssh2/下载,我们用的是ganymed-ssh2-build210.zip

在eclipse里新建一个测试工程,并将解压后的ganymed-ssh2-build210.jar拷到工程的lib目录下,然后在工程属性的java build path里添加这个jar的library。


二、ssh

将解压后的examples目录下的Basic.java 拷到工程的src目录,编译运行以后可以在控制台看到输出结果。除了执行一条命令,也可以执行一个shell脚本。

测试脚本test.sh:

#! /bin/sh
echo "testing shell"
ls

运行cmd的Java程序:

public boolean realRun(String cmd) {
		cmd = test.sh
//		LocalShellExecutor exe = new LocalShellExecutor();
		RmtShellExecutor exe = new RmtShellExecutor("192.168.1.118", "22", "root", "123456");
//		RmtShellExecutor exe = new RmtShellExecutor("127.0.0.1", "22", "root", "123456");
		logger.info("cmd:" + cmd);
		int ret = exe.exec(cmd);
		outErr = exe.getErrorMessage();
		outStr = exe.getResult();
		result = (ret == 0 ? true : false);
		if (!result) {
			logger.error("err:" + outErr);
		}
		logger.info("outStr:" + outStr);
		return result;
	}

本地调用:

package scnas.controller;

import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import scnas.iface.ShellExecutor;
import scnas.model.Const;

public class LocalShellExecutor implements ShellExecutor {
    /**标准输出**/
    private String outStr;
    /**错误输出**/
    private String outErr;
    
        
	@Override
	public int exec(String cmds) {
		int ret = -1;
		try{
			final Process process = Runtime.getRuntime().exec(cmds);
//			Thread inputThread = new Thread(new Runnable(){
//				@Override
//				public void run() 
//				{
					try {
						InputStream inputStream = process.getInputStream();
						InputStreamReader reader = new InputStreamReader(inputStream);
						int readed = 0;
						char[] chs = new char[1024];
						StringBuffer buffer = new StringBuffer();
						while( (readed=reader.read(chs)) != -1 ){		
							buffer.append(chs,0,readed);
						}
						
						outStr = buffer.toString();
						
						logger.info(outStr);

					}catch(Exception ex){
						logger.error(ex.getMessage(), ex);
					}
//				}
//			});
			
//			Thread errorThread = new Thread(new Runnable(){
//				@Override
//				public void run() 
//				{
					try {
						InputStream inputStream = process.getErrorStream();
						InputStreamReader reader = new InputStreamReader(inputStream);
						int readed = 0;
						char[] chs = new char[1024];
						StringBuffer errorBuffer = new StringBuffer();
						while( (readed=reader.read(chs)) != -1 )
						{
							errorBuffer.append(chs,0,readed);
						}
						outErr = errorBuffer.toString();
					}catch(Exception ex){
						logger.error(ex.getMessage(), ex);
					}
//				}
//			});
			
//			errorThread.start();
//			inputThread.start();
			
			process.getOutputStream().close(); 
						
			ret = process.waitFor(); 
			
		} catch(Exception e){ 
			outErr = e.getMessage();
		} 
		
		if( ret != 0 )
			logger.error("LocalShellExecutor ERROR: " + outErr);
		logger.info("LocalShellExecutor: " + outStr);
		return ret;
	}

	@Override
	public String getErrorMessage() {
		return outErr;
	}

	@Override
	public String getResult() {
		return outStr;
	}
	
	public static void main(String args[]){
		LocalShellExecutor localShellExecutor = new LocalShellExecutor();
		localShellExecutor.exec(Const.PATH + Const.HOST);
	}

	public String getOutStr() {
		return outStr;
	}

	public void setOutStr(String outStr) {
		this.outStr = outStr;
	}

	public String getOutErr() {
		return outErr;
	}

	public void setOutErr(String outErr) {
		this.outErr = outErr;
	}


	private static final Log logger = LogFactory.getLog(LocalShellExecutor.class);
}

远程调用:

package scnas.controller;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import scnas.iface.ShellExecutor;
import scnas.model.Const;
import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

/**
 * 远程执行shell脚本类
 */
public class RmtShellExecutor implements ShellExecutor{
    
    /**  */
    private Connection conn;
    /** 远程机器IP */
    private String     ip;
    /** 用户名 */
    private String	port;
    private String     usr;
    /** 密码 */
    private String     psword;
    private String     charset = Charset.defaultCharset().toString();

    private static final int TIME_OUT = 1000 * 5 * 60;
    
    /**标准输出**/
    private String outStr;
    /**错误输出**/
    private String outErr;
    
    private static final Log logger = LogFactory.getLog(RmtShellExecutor.class);

    /**
     * 构造函数
     * @param ip
     * @param usr
     * @param ps
     */
    public RmtShellExecutor(String ip, String port, String usr, String ps) {
        this.ip = ip;
        this.port = port;
        this.usr = usr;
        this.psword = ps;
    }

    /**
     * 登录
     * 
     * @return
     * @throws IOException
     */
    private boolean login() throws IOException {
        conn = new Connection(ip, Integer.parseInt(port));
        conn.connect();
        return conn.authenticateWithPassword(usr, psword);
    }

    /**
     * 执行脚本
     * 
     * @param cmds
     * @return
     * @throws Exception
     */
    @Override
    public int exec(String cmds){
        InputStream stdOut = null;
        InputStream stdErr = null;

        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);
                ret = session.getExitStatus();
            } else{
            	outErr = "登录远程机器失败:" + ip;
            }
        }catch(Exception e){
        	outErr = "远程操作失败:" + ip;
        }finally{
            if (conn != null) {
                conn.close();
            }
            IOUtils.closeQuietly(stdOut);
            IOUtils.closeQuietly(stdErr);
        }
        
		if( ret != 0 ){
			logger.error("RmtShellExecutor ERROR: " + outErr);
//			Loginfo loginfo = new Loginfo("ERROR", "", "RmtShellExecutor", cmds + " - " + outStr);
//			scnasService.loginfoAdd(loginfo);
		}else{
			logger.info(cmds +  ": " + outStr);
//			Loginfo loginfo = new Loginfo("INFO", "", "RmtShellExecutor", cmds + " - " + outErr);
//			scnasService.loginfoAdd(loginfo);
		}
		
        return ret;
    }
    
    public int exec(String cmds, boolean wait){
        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);
                
            	session.waitForCondition(ChannelCondition.EXIT_STATUS, TIME_OUT );
            	ret = session.getExitStatus();
            } else{
            	outErr = "登录远程机器失败:" + ip;
            }
        }catch(Exception e){
        	outErr = "远程操作失败:" + ip;
        }finally{
            if (conn != null) {
                conn.close();
            }
        }
        
		if( ret != 0 )
			logger.error("RmtShellExecutor wait ERROR!");
		
        return ret;
    }    
    
    public void scp(String localfile, String remoteDirectory){
        try {
			if (login()) {
			    SCPClient sCPClient = new SCPClient(conn);
			    sCPClient.put(localfile, remoteDirectory, "0755");
			} else{
				outErr = "登录远程机器失败:" + ip;
			}
		} catch (IOException e) {
			outErr = "远程操作失败:" + ip;
		}finally{
            if (conn != null) {
                conn.close();
            }
        }
    }

    /**
     * @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));
            buf = new byte[1024];
        }
        return sb.toString();
    }

	@Override
	public String getErrorMessage() {
		return outErr;
	}

	@Override
	public String getResult() {
		return outStr;
	}

	public Connection getConn() {
		return conn;
	}

	public void setConn(Connection conn) {
		this.conn = conn;
	}

	public String getIp() {
		return ip;
	}

	public void setIp(String ip) {
		this.ip = ip;
	}

	public String getPort() {
		return port;
	}

	public void setPort(String port) {
		this.port = port;
	}

	public String getUsr() {
		return usr;
	}

	public void setUsr(String usr) {
		this.usr = usr;
	}

	public String getPsword() {
		return psword;
	}

	public void setPsword(String psword) {
		this.psword = psword;
	}

	public String getCharset() {
		return charset;
	}

	public void setCharset(String charset) {
		this.charset = charset;
	}

	public String getOutStr() {
		return outStr;
	}

	public void setOutStr(String outStr) {
		this.outStr = outStr;
	}

	public String getOutErr() {
		return outErr;
	}

	public void setOutErr(String outErr) {
		this.outErr = outErr;
	}

	public static int getTimeOut() {
		return TIME_OUT;
	}

	public static Log getLogger() {
		return logger;
	}

	public static void main(String args[]){
        RmtShellExecutor exe = new RmtShellExecutor("10.10.1.101", "22", "root", "123456");
        System.out.println(Const.SHELL + Const.PATH + Const.HOST);
//        System.out.println("exit state:" + exe.exec("gluster volume status vol4 detail"));
//        System.out.println("result:" + exe.getResult());
//        System.out.println("err:" + exe.getErrorMessage());
//        exe.scp("/tmp/1", "/tmp");
        exe.exec("scnas peer status");
//        System.out.println("result:" + exe.getResult());
    }
    
}

在eclipse里运行以后的结果为:

Here is some information about the remote host:
testing shell
1
test.sh
ExitCode: 0

需要注意的是在一个session里只能执行一次命令,因此如果想在server上执行多个命令,要么打开多个session,要么在一个session里去执行一个shell脚本,shell脚本里去执行多个命令。

每次执行完以后,如果正确将返回ExitCode: 0,因此程序里可以通过sess.getExitStatus()来判断命令是否被正确执行。


三、 scp

首先在程序里import ch.ethz.ssh2.SCPClient;   

然后通过下面的方法来实现:

SCPClient scpClient = conn.createSCPClient();   
scpClient.put("localFiles", "remoteDirectory"); //从本地复制文件到远程目录   
scpClient.get("remoteFiles","localDirectory"); //从远程获取文件

如上

public void scp(String localfile, String remoteDirectory){}

例如:

scpClient.put("D:\\localTest.txt", "/home/bill/"); 需要注意的是windows的本地目录要用双斜杠来分隔目录。
scpClient.put("/home/bill/remoteTest.txt", "D:\\");


四、sftp

首先在程序里import ch.ethz.ssh2.SFTPv3Client;

SFTPv3Client sftpClient = new SFTPv3Client(conn);   
sftpClient.mkdir("newRemoteDir", 0755); //远程新建目录 ,第二个参数是创建的文件夹的读写权限  
sftpClient.rmdir("oldRemoteDir"); //远程删除目录

另外还有创建删除文件,读写文件等接口,参见http://www.ganymed.ethz.ch/ssh2/javadoc/ch/ethz/ssh2/SFTPv3Client.html



Ganymed SSH-2

标签:

原文地址:http://my.oschina.net/u/2260184/blog/512114

(0)
(0)
   
举报
评论 一句话评论(0
0条  
登录后才能评论!
© 2014 mamicode.com 版权所有 京ICP备13008772号-2
迷上了代码!