telnet协议采集HP-UX服务器简介

      近期我们的网管项目要新接进一批操作系统是HP-UX的机器,采集方式还是大家很熟悉的Telnet,通过java程序模拟发送shell命令采集获取机器的CPU使用率,内存使用率和磁盘使用率等设备的性能指标,但是使用以前采集AIX,SOLARIS平台的代码却采集不成功,程序发送密码过去,却不能拿到shell的返回,原telnet采集代码如下:

    

public class TelnetUtil {
	// 重新定义TelnetUtil的日志跟踪信息
	private Logger logger;
	protected String host;
	protected int port = 23;
	private TelnetClient tc;
	
	// 这两个需要供子类共用
	protected InputStream in;
	protected PrintStream out;
	
	private Integer WAIT_TIME = 3000; // 搞长一点,修改为3秒
	private static final String EOL = "\r\n";
	
	@SuppressWarnings("unused")
	private String prompt;
	// 任务id
	protected long taskId;

	/**
	 * IP地址,端口号
	 * 
	 * @param host
	 *            String
	 * @param port
	 *            int
	 */
	public TelnetUtil(String host) {
		this.host = host;
	}

	/**
	 * IP地址,端口号
	 * 
	 * @param host
	 *            String
	 * @param port
	 *            int
	 */
	public TelnetUtil(String host, int port, String prompt) {
		this.prompt = prompt;
		this.host = host;
		this.port = port;
	}

	public TelnetUtil(String host, int port) {
		this.host = host;
		this.port = port;
	}
	
	/**
	 * 
	 * @param host 地址
	 * @param port 端口
	 * @param taskId 任务id
	 */
	public TelnetUtil(String host,int port,Long taskId) {
		this(host,port);
		this.taskId = taskId;
		logger = Logger.getLogger("/UTIL/TELNETUTIL/id_" + taskId,
				Logger.ALL, true); 
	}

	/**
	 * 初始化Telnet Client
	 * 
	 * @throws InvalidTelnetOptionException
	 * @throws IOException
	 * @throws SocketException
	 * 
	 * @throws Exception
	 */
	private void initTelnetClient() throws InvalidTelnetOptionException,
			SocketException, IOException {
		
		logger.infoT("start task id is " + taskId);
		tc = new TelnetClient();
		TerminalTypeOptionHandler ttopt = new TerminalTypeOptionHandler(
				"vt100", false, false, true, false);
		EchoOptionHandler echoopt = new EchoOptionHandler(true, false, true,
				false);
		SuppressGAOptionHandler gaopt = new SuppressGAOptionHandler(true, true,
				true, true);
		tc.addOptionHandler(ttopt);
		tc.addOptionHandler(echoopt);
		tc.addOptionHandler(gaopt);
		tc.setDefaultTimeout(30000);
		// tc.setSoTimeout(10000);
		tc.connect(host, port);
		tc.setReaderThread(true);
		in = tc.getInputStream();
		logger.debugT("telnet " + host + ":" + port);	
		out = new PrintStream(tc.getOutputStream());
	}

	/**
	 * 登录服务器
	 * 
	 * @param userName
	 *            String
	 * @param password
	 *            String
	 * @throws Exception
	 */
	public void login(String userName, String password) throws Exception {
		if (tc == null)
			initTelnetClient();
		String res = getResponseAsString();
		logger.debugT("be ready for send userName:" + res);
		write(userName);
		waiting(); // 增加等待时间
		res = getResponseAsString();
		logger.debugT("be ready for send password:" + res);
		write(password);
		logger.infoT("password: = " + password);
//		waiting(); // 增加等待时间
		Thread.sleep(10000);
		res = getResponseAsString();
		if (res.contains("incorrect")) {
			throw new java.lang.Exception("UserOrPasswordError");
		}
		logger.debugT("be ready for send command:" + res);
	}

	/**
	 * 获取返回数据
	 * 
	 * @return String
	 * @throws Exception
	 */
	private String getResponseAsString() {
		/*
		 * int startBlock = 0; int endBlock = 0; while (true) { startBlock =
		 * readThread.getBlock(); waiting(); endBlock = readThread.getBlock();
		 * if (endBlock == startBlock) { res = readThread.getResult(); break; }
		 * }
		 */

		StringBuilder sb = new StringBuilder(1024);
		byte[] buff = new byte[1024];

		int ret_read = 0;
		try {
			do {
				ret_read = in.read(buff);
				if (ret_read > 0) {
					sb.append(new String(buff, 0, ret_read));
				}
			} while (ret_read >= 0);
		} catch (IOException e) {
			e.printStackTrace();
			// log.exception(e);
		}
		return sb.toString();
	}

	/**
	 * 发送命令
	 * 
	 * @param command
	 *            String
	 * @throws Exception
	 */
	public String sendCommand(String command) throws Exception {
		System.out.println("send:" + command);
		command = command + EOL;
		out.print(command);
		out.flush();
		waiting(); // update by ChangPeng 2012-03-13 改为睡眠3秒,此处多睡1秒,防止输出命令后返回流的数据还未返回
		String result =  getResponseAsString();
		logger.infoT("send command result:" + result);
		return result;
	}

	/**
	 * 发送数据
	 * 
	 * @param value
	 *            String
	 */
	protected void write(String value) throws Exception {
		out.println(value);
		out.flush();
	}

	/**
	 * 发送命令后,等待500ms,至输入流中有可读数据
	 * 
	 * @throws Exception
	 */
	private void waiting() throws Exception {
		Thread.sleep(WAIT_TIME);
	}

	/**
	 * 断开连接
	 * 
	 * @throws Exception
	 */
	public void disConnect() throws Exception {
		logger.infoT("end task id is " + taskId + "disconnet");
		tc.disconnect();
		tc = null;
	}

	public static void main(String[] srgs) {
		try {
			TelnetUtil tu = new TelnetUtil("10.25.3.174", 22, "\r\n");
			tu.login("yangran", "123456");
			String res = tu
					.sendCommand("cat /proc/meminfo |grep MemFree |cut -d: -f 2|awk '($1~/^[0-9]+$/) { print $1}'");
			System.out.println("res:" + res);
			tu.disConnect();
		} catch (Exception e) {
			System.out.println(e.getClass().getCanonicalName());
			// e.printStackTrace();
		}
	}
}


       采用上面的类调用login方法,却无法模拟登陆hp_ux机器,在网上查了下,原来hp-ux的采集方式和其它linux机器是不一样的,需要在out.println(value);命令之前先做一个while(true)循环,守候到TelnetClient的InputStream得到相应的prompt值,网上代码prompt值不是"#"就是">",但是在我们服务器上用secureCRT测试发现prompt是"$",参照网上的代码,前面的登陆过程果然能通过,并顺利捕获返回的shell值,但是如果有些空行,打印返回值还是有些乱码的,这个无关大局,就没予以关注了,但是输出命令却发现一个令人苦恼的问题,因为命令中含有"$",那样readUntil就会认为是prompt"$"给提前终止了,因为InputStream的read方法这个还会带出PrintStream out输出的命令原文,其中就含有"$"。经过考虑后发现一个巧妙的解决办法,在循环中记下inputStream读取的前面的char字符,因为最后的prompt之前的char必然是'\n'换行符,这个问题就顺利得到解决,代码如下(注意TelnetHPUXUtil 是继承自上面的TelnetUtil类的,有些方法是调用了上面父类的方法)。

public class TelnetHPUXUtil extends TelnetUtil {

	/**
	 * 日志
	 */
	private final Logger logger;

	/**
	 * 所有HP-UX的机器的IP数组
	 */
	public final static String[] HP_UX_MACHINE_IPARR = { "10.26.106.193",
			"10.26.106.194", "10.26.106.195", "10.26.106.196", "10.26.106.214" };

	public final static String SPECIAL_IP = "10.26.106.214";

	private String tranencoding = "iso-8859-1";

	private String aixencoding = "gb2312";

	private TelnetClient telnet = new TelnetClient();

	private char prompt = '$';

	/**
	 * 构造函数
	 * 
	 * @param host
	 *            服务器地址
	 * @param port
	 *            端口
	 * @param user
	 *            用户帐号
	 * @param password
	 *            用户口令
	 * @param taskId
	 *            任务ID
	 */
	public TelnetHPUXUtil(String host, int port, String user, Long taskId) {
		super(host, port);
		this.taskId = taskId;
		logger = Logger.getLogger("/UTIL/TelnetHPUXUtil/id_" + taskId,
				Logger.ALL, true);
		if ("root".equals(user)) {
			this.prompt = '#';
		} else {
			this.prompt = '$';
		}

		// 登陆
		// loginHPUX(user, password);
	}

	/**
	 * 登陆HP-UX服务器
	 * 
	 * @param user
	 * @param password
	 */
	public void loginHPUX(String user, String password) {
		logger.infoT("start hp-ux task id is " + taskId);
		try {

			telnet.connect(host, port);
			in = telnet.getInputStream();
			out = new PrintStream(telnet.getOutputStream());
			readUntil("login: ");
			write(user);
			readUntil("Password: ");
			write(password);
			readUntil(prompt + "");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 读取返回的字符串
	 * 
	 * @param pattern
	 *            结尾的字符串
	 * @return 返回返回的字符串
	 */
	private String readUntil(String pattern) {
		try {

			char lastChar = pattern.charAt(pattern.length() - 1);
			StringBuilder sb = new StringBuilder();

			char ch = (char) in.read();

			while (true) {
				sb.append(ch);
				if (ch == lastChar) {
					if (sb.toString().endsWith(pattern)) {
						String temp = sb.toString();
						return temp;
					}
				}
				ch = (char) in.read();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 读取返回的字符串
	 * 
	 * @param pattern
	 *            结尾的字符串
	 * @return 返回返回的字符串
	 */
	private String readUntilCommand(String pattern) {
		try {

			char lastChar = pattern.charAt(pattern.length() - 1);
			StringBuilder sb = new StringBuilder();

			char ch = (char) in.read();
			char beforeChar = 0;

			while (true) {
				sb.append(ch);
				if (ch == lastChar && beforeChar == '\n') {
					if (sb.toString().endsWith(pattern)) {
						String temp = sb.toString();
						logger.infoT(new String(temp.getBytes(tranencoding),
								aixencoding));
						return temp;
					}
				}
				beforeChar = ch;
				ch = (char) in.read();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 发送命令
	 */
	public String sendCommand(String command) {
		try {
			write(command);
			String result = readUntilCommand(prompt + "");
			// logger.infoT("command result: === " + result);
			return result;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public void disconnect() {
		logger.infoT("end hp ux task id is " + taskId + "disconnet");
		try {
			telnet.disconnect();
			telnet = null;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		// char ch = '\n';
	}

}

  该文草草写就,谨对网上的参考文章的作者表示感谢,参考资料如下:

   http://hi.baidu.com/zhengmh/blog/item/c7199da22ed9a6afcbefd0ba.html

  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值