SSHByFortress.java 8.04 KB
package com.sitech.util.upload;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

/**
 * SH 通过堡垒机执行命令
 * @author Administrator
 *
 */
public class SSHByFortress {
	private String host_ip;
	private int port;
	private String login_id;
	private String password;
	private boolean autorized = false;

	Session session;
	Channel channel;
	InputStream inputStream ;  
	OutputStream outputStream ;
	
	// 存放命令执行结果
	private String result = new String();
	
	private static final String END_FLAG = "## End Command ##";
	private static final String END_CMD = "echo \"" + END_FLAG + "\"";
	private static final long TIME_OUT = 2 * 60 * 1000l;

	private Logger logger = Logger.getLogger(SSHByFortress.class);

	/**
	 * 构造函数
	 * 
	 * @param host_ip
	 * @param port
	 * @param login_id
	 * @param password
	 */
	public SSHByFortress(String host_ip, int port, String login_id, String password) {
		this.host_ip = host_ip;
		this.port = port;
		this.login_id = login_id;
		this.password = password;
	}
	

	/**
	 * 执行命令
	 * @param cmd
	 * @return
	 * @throws Exception
	 */
	public String doCommand(String cmd) throws Exception{
		String newCmd = cmd + ";" + END_CMD;
		if(!sendInfo(newCmd, END_FLAG)){
			throw new RuntimeException("Exception while login dst host by fortress: ");
		}
		
		if(null == result){
			throw new RuntimeException("Null return while do command: " + cmd);
		}
		
		// 处理结果,去掉无用信息
		result = formatNVT(result, newCmd);
		
		StringBuffer sb = new StringBuffer();
		sb.append("******************* Begin ******************************\n");
		sb.append("Cmd: " + cmd + "\n");
		sb.append("Result: " + result + "\n");
		sb.append("******************* End ******************************\n");
		logger.info(sb.toString());
		
		return result;
	}
	
	/**
	 * 处理结果
	 * @param str
	 * @param cmd
	 * @return
	 */
	private String formatNVT(String str, String cmd){
		str = Pattern.compile("\\[[0-9]*[;]?[0-9]*m", Pattern.DOTALL).matcher(result).replaceAll("");
		str = str.replace(cmd, "").replace(END_FLAG, "").replaceFirst("\n", "");
		return str;
	}
	
	/**
	 * 发送命令,并获得执行结果
	 * @param command
	 * @param regext
	 * @return
	 * @throws Exception
	 */
	private boolean sendInfo(String command, String regext) throws Exception {
		command = (null == command) ? "" : command;
		command = (!command.endsWith("\n")) ? command + "\n" : command;
		
		logger.info("-- sendInfo: " + command);
		
		outputStream.write(command.getBytes());
		outputStream.flush();

		int ch = -1;
		long startTime = System.currentTimeMillis();

		StringBuffer _result = new StringBuffer();
		boolean _isEnd = false;

			while ((ch = (char) inputStream.read()) >= -1) {
				if (ch == -1) {
					throw new IllegalArgumentException("接收不到消息");
				}

				_result.append((char) ch);
				
				//System.out.println(_result.toString());
				
				if(null != regext && !regext.isEmpty()
						&& _result.toString().endsWith(regext.trim())){
					if(!_result.toString().endsWith(END_CMD.substring(0, END_CMD.length()-1))){
						this.result = _result.toString();
						
						logger.info("-- result: " + this.result);
						_isEnd = true;
					}
					
				}

				if (inputStream.available() == 0) {
					if(_isEnd || null == regext || regext.isEmpty() ){
						return true;
					}
				}
				
				if (System.currentTimeMillis() - startTime > TIME_OUT) {
					throw new RuntimeException("TIME_OUT :" + command);
				}
			}
		
		
		return false;
	}

	/**
	 * 登录堡垒机
	 */
	public void initial() {
		logger.info("Login Fortress Host : " + host_ip + "...");
		try {
			JSch jsch = new JSch();
			session = jsch.getSession(login_id, host_ip, port);
			session.setPassword(this.password);
			session.setConfig("StrictHostKeyChecking", "no");
			// making a connection with timeout.
			session.connect(30000);

			if (!session.isConnected()) {
				throw new RuntimeException("session.isConnected() == false");
			}

			logger.info("Success Login Fortress Host : " + host_ip);
			this.autorized = true;
		} catch (Exception e) {
			this.autorized = false;
			throw new RuntimeException("Failed Login Fortress Host : "
					+ host_ip + "|" + port + "|" + login_id + "!", e);
		}
	}
	
	/**
	 * 登录目标主机
	 * ————————————————————————————————————————————
	 * Input Host IP: 172.21.0.31
	 * Input Protocols Type:ssh
	 * Input Hostname:10.7.72.73+idep-10.7.84.9-SSH
	 * Input User Prompt:
	 * login:
	 * Input Password Prompt:
	 * Input User:
	 * Input Password:	
	 * ————————————————————————————————————————————
	 */
	public String loginDst(String[][] params){
		try{
			channel = session.openChannel("shell");
			if (channel != null) {
				channel.connect();
				
				inputStream=channel.getInputStream(); 
				outputStream = channel.getOutputStream();
				for(int i=0;i<params.length;i++){
					Thread.sleep(200);
					
					if(!sendInfo(params[i][0], params[i][1])){
						throw new RuntimeException("Exception while login dst host by fortress: ");
					}
				}
			}
		}catch(Exception e){
			result = "连接目标主机出错:" + e.getMessage();
			throw new RuntimeException("Exception while loginDst", e);
		}
		
		return result;
	}

	/**
	 * 关闭连接
	 */
	public void close() {
		if (null != inputStream) {
			try {
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		if (null != outputStream) {
			try {
				outputStream.flush();
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		if (null != channel) {
			try {
				channel.disconnect();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		if (session != null && session.isConnected()) {
			session.disconnect();
			logger.info("Disconnect successed, ip=" + this.host_ip);
		} else {
			logger.info("Disconnect ip=has exception before" + this.host_ip);
		}
	}

	/**
	 * 堡垒机是否认证OK
	 */
	public boolean isAuthorized() {
		return this.autorized;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// 堡垒机IP地址
		String ipAddr = "172.21.0.31";
		// 堡垒机登录端口
		int port = 22;
		// 堡垒机用户名
		String username = "bnms";
		// 堡垒机密码
		String password = "bnms";
		
		// 登录目标主机参数 [0]要输入的参数值;[1]代表期待返回的提示字符串
	    String[][] params = new String[7][2];//
		
	    // 输入目标资源的地址
		params[0][0] = "10.7.84.9";
		params[0][1] = "Input Protocols Type:";
		
		// 输入登录目标资源的协议(ssh、telnet及ssh2均可以)
		params[1][0] = "ssh";
		params[1][1] = "Input Hostname:";
		
		// 输入登录源地址+资源名
		params[2][0] = "10.7.72.73+idep-10.7.84.9-SSH";
		params[2][1] = "Input User Prompt:";
		
		// 此处输入用户名提示符。如果登录方式为telnet则此处填入
		params[3][0] = "username:idep_sr1";
		params[3][1] = "login:";
		
		// 如为ssh方式登录则此处填入null即可
		params[4][0] = "null";
		params[4][1] = "Input Password Prompt:";
		
		// 此处填入密码提示符,一般为password:
		params[5][0] = "password:idep_sr1";
		params[5][1] = "Input User:";
		
		// 输入登录目标资源的从帐号
		params[6][0] = "idep";
		params[6][1] = "Input Password:";
		
		// 输入登录目标资源的密码
		params[7][0] = "abcd";
		params[7][1] = "Input Password: ";


		SSHByFortress ssh = null;
		try {
			//链接堡垒机
			ssh = new SSHByFortress(ipAddr, port, username,	password);
			// 登录堡垒机
			ssh.initial();
			// 登录目标主机
			ssh.loginDst(params);
			// 在目标主机上执行命令
			ssh.doCommand("pwd");
			
			ssh.doCommand("ls -l");
			
			ssh.doCommand("uname -a");
			
			ssh.doCommand("vmstat 1 3");
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			ssh.close();
		}
	}
}