qileilove

blog已经转移至github,大家请访问 http://qaseven.github.io/

打造自己的Linux服务器监控小工具

 周末在家蛮无聊的,思考人生的同时突发奇想就写一个服务器监控的小工具吧。学JAVA快1年了,刚好检验一下自己!
  仔细想想呢估计作用可能也有限,毕竟外面各种监控工具也很多,初衷其实也只是练练手,加上平时比较懒,那么为了更方便的看服务器性能指标,所以就选了这个题材咯,那么就开始吧。
  不过优点也是有的嘛,至少不需要在服务器端装一个脚本之类的了。
  一、小工具的功能
  1 能够读取服务器CPU,IO,Memory的性能指标并在页面展示出来
  2 把监控的信息打印到文件,方便进行数据分析
  二、准备工作
  java开发环境、JDK1.7+、 Eclipse
  maven环境
  git
  三、使用到的框架
  前台:
  JS的FLOT框架
  后台:
  SpringMVC框架
  工作流程图(其实蛮简单的)
  项目结构目录
  四、实现代码
  主要的功能类
  1 LinuxService 提供服务器指令输入的服务入口
  2 LinuxConnectionPool  把服务器连接对象保存起来,每一次获得请求时会先检查连接是否在池子中存在,有的话直接用,没有的话就创建一个新的
  3 LinuxConnection  服务器连接对象,负责创建connection
  4 LinuxSessionHandle 负责创建session并执行CMD指令最后销毁session
  5 EntityBaseUtil 提供了把Linux返回的结果转换成比较适合装入实体类的方法String Transfer ListString[]
 代码
  1 LinuxService
package com.sunfan.monitor.service;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.sunfan.monitor.manager.pool.LinuxConnectionPool;
import com.sunfan.monitor.platform.IConnectable;
import com.sunfan.monitor.platform.linux.LinuxSessionHandle;
/**
*
* @author sunfan
*
*/
@Component
public class LinuxService {
private  String defaultTopComand = "top -b -n 1";
private  String defaultMpstatComand = "mpstat -P ALL";
private  String defaultFreeCommand = "free -m";
private  String defaultIostatCommand = "iostat -d -m";
@Autowired
private LinuxConnectionPool pool ;
@Autowired
private LinuxSessionHandle handle;
/**
* execute default command "top -b -n 1" and return String type reslut
*
* @param url  server's ip
* @param user  login name
* @param password login password
* @return
* @throws IOException
*/
public String topMonitor(String url,String user,String password) throws IOException{
return this.executeCommand(url, user, password, defaultTopComand);
}
/**
* execute default command "mpstat -P ALL" to get cpus performance
*
* @param url
* @param user
* @param password
* @return
* @throws IOException
*/
public String cpuMonitor(String url,String user,String password) throws IOException{
return this.executeCommand(url, user, password, defaultMpstatComand);
}
/**
* execute default command "free -m" to get memory performance
* @param url
* @param user
* @param password
* @return
* @throws IOException
*/
public String memoryMonitor(String url,String user,String password) throws IOException{
return this.executeCommand(url, user, password, defaultFreeCommand);
}
/**
* execute default command "free -m" to get memory performance
* @param url
* @param user
* @param password
* @return
* @throws IOException
*/
public String inputOutputMonitor(String url,String user,String password) throws IOException{
return this.executeCommand(url, user, password, defaultIostatCommand);
}
public String executeCommand(String url,String user,String password,String command) throws IOException{
IConnectable lc =  pool.borrowObject(url,user,password);
return handle.executeCommand(lc.getConnection(),command);
}
}
  2 LinuxConnectionPool
package com.sunfan.monitor.manager.pool;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.sunfan.monitor.manager.IConnectionPool;
import com.sunfan.monitor.platform.IConnectable;
import com.sunfan.monitor.platform.linux.LinuxConnection;
/**
*
* @author sunfan
*
*/
@Component
public class LinuxConnectionPool implements IConnectionPool {
private Logger logger = LoggerFactory.getLogger(getClass());
private Map<String, IConnectable> connectionPool = new HashMap<String, IConnectable>();
/**
* save connecion in the connectionPool,if conn is already exist return
* false else return true
*
* @param conn
* @return
*/
public synchronized Boolean saveObject(IConnectable conn) {
String key = rewardConnectionKey(conn);
if (isExist(key)) {
logger.info("this key{} has already exist", key);
return false;
}
connectionPool.put(key, conn);
return true;
}
/**
* borrow connection object in the connect-pool
*
* @param key
* @return
*/
public IConnectable borrowObject(String key) {
if (!isExist(key)) {
throw new IllegalArgumentException("key not found:" + key);
}
return connectionPool.get(key);
}
public IConnectable borrowObject(String url,String user,String password){
String key = this.rewardConnectionKey(url, user, password);
if (!isExist(key)){
try {
LinuxConnection connect = new LinuxConnection(url, user, password);
connectionPool.put(key, connect);
return connect;
} catch (IOException e) {
throw new RuntimeException("connection error"+url,e);
}
}else {
return connectionPool.get(key);
}
}
/**
* borrow connection object in the connect-pool if the connection hasn't in
* the connectionPool return null,else return connect object
*
* @param conn
* @return
*/
public IConnectable borrowObject(IConnectable conn) {
String key = rewardConnectionKey(conn);
return borrowObject(key);
}
/**
* close single connection in the connection-pool and close/release of this
* connection
*
* @param conn
* @throws IOException
*/
public void remove(IConnectable conn) throws IOException {
String key = rewardConnectionKey(conn);
remove(key);
}
/**
* close single connection in the connection-pool and close/release of this
* connection
*
* @param conn
* @throws IOException
*/
public synchronized void remove(String key) throws IOException {
if (!isExist(key)) {
throw new IllegalArgumentException(key + "is not exist");
}
connectionPool.get(key).close();
connectionPool.remove(key);
}
/**
* delete every connection in the connection-pool and also close/release of
* all connection
*
* @throws IOException
*/
public void clear() throws IOException {
for (String keyString : connectionPool.keySet()) {
connectionPool.get(keyString).close();
}
connectionPool.clear();
}
/**
* according to the connection to generate key if the connecion is not equal
* null return url/usr/password
*
* @param conn
* @return
*/
public String rewardConnectionKey(IConnectable conn) {
return conn.getUrl() + "/" + conn.getUser() + "/" + conn.getPassword();
}
public String rewardConnectionKey(String url, String user, String password) {
return url + "/" + user + "/" + password;
}
/**
* To confirm whether the connectionPool has this key if already has return
* true else return false
*
* @param key
* @return
*/
public Boolean isExist(String key) {
return connectionPool.containsKey(key);
}
}
  3 LinuxConnection
package com.sunfan.monitor.platform.linux;
import java.io.Closeable;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.sunfan.monitor.platform.IConnectable;
import com.trilead.ssh2.Connection;
import com.trilead.ssh2.ConnectionInfo;
/**
*
* @author sunfan
*
*/
public class LinuxConnection implements IConnectable, Closeable {
Logger log = LoggerFactory.getLogger(LinuxConnection.class);
private String url, user, password;
private Connection connection;
/**
* init server's connect
*
* @param url
* @param user
* @param password
* @throws IOException
*/
public LinuxConnection(String url, String user, String password) throws IOException{
this.url = url;
this.user = user;
this.password = password;
this.connection = createConnection();
}
/**
* this method will establish connection unless username or password
* incorrect and remote server is not find
*
* @return connection
* @throws IOException
*/
private Connection createConnection() throws IOException {
connection = new Connection(url);
ConnectionInfo info = connection.connect(); // establish connection
if (false == connection.authenticateWithPassword(user, password)){
log.error("connect server failed,please check the username and password. " + this.user + " " + this.password);
throw new IllegalArgumentException("connection remote server fail");
}
return connection;
}
/**
* close connection
*/
@Override
public void close() throws IOException {
if (connection != null)
this.connection.close();
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Connection getConnection() {
return connection;
}
public void setConnection(Connection connection) {
this.connection = connection;
}
}
  4 LinuxSessionHandle
package com.sunfan.monitor.platform.linux;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.sunfan.monitor.platform.IMonitorable;
import com.trilead.ssh2.Connection;
import com.trilead.ssh2.Session;
import com.trilead.ssh2.StreamGobbler;
/**
*
* @author sunfan
*
*/
@Component
public class LinuxSessionHandle implements IMonitorable,Closeable{
Logger logger = LoggerFactory.getLogger(LinuxSessionHandle.class);
private Session session;
/**
* open session then execute commands on remote server and return the result of it
* @param command
* @return String
* @throws IOException
*/
public synchronized String executeCommand(Connection conn,String command) throws IOException {
String str="";
try {
session = conn.openSession();
session.execCommand(command);
str = this.read().toString();
} catch (Exception e) {
session.ping();
throw new IOException("session exception",e);
}
finally{
close();
}
return str;
}
/**
* read the result of remote server execute commands
* @return
* @throws IOException
*/
private StringBuffer read() throws IOException{
InputStream stdout = new StreamGobbler(session.getStdout());
BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
String tempString = null;
// readLine()每次调用都默认会读一行
StringBuffer str = new StringBuffer();
while ((tempString = br.readLine()) != null) {
str.append(tempString+"\r\n");
}
br.close();
return str;
}
/**
* close session
*/
@Override
public void close() throws IOException {
if (this.session != null) this.session.close();
}
}
5 EntityBaseUtil
package com.sunfan.monitor.entity.util;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author sunfan
*
*/
public class EntityBaseUtil {
/**change String result to List<String> result by split "\r\n"
* remove the content above flag
* to transfer List<String> ---> list<String[]> by .split("\\s{1,}")
* @param result
* @param flag
* @return
*/
public List<String[]> transferListofStringArray(String result,String flag){
List<String> resList = this.transferList(result);
List<String> contentList = this.removeResultHead(resList,flag);
return this.transferArrayOfList(contentList);
}
/**
* change String result to List<String> result by split "\r\n"
* @param result
* @return List<String>
*/
public List<String> transferList(String result){
String[] strs = result.split("\r\n");
List<String> list = new ArrayList<String>();
for(String s:strs){
list.add(s);
}
return list;
}
/**remove the content above flag
*
* @return List<String>
*/
public List<String> removeResultHead(List<String> resultList,String flag){
List<String> contentList = new ArrayList<String>();
contentList.addAll(resultList);
for(String res:resultList){
if(res.contains(flag)){
break;
}
contentList.remove(res);
}
return contentList;
}
/**to transfer List<String> ---> list<String[]> by .split("\\s{1,}")
*
* @param contentList
* @return List<String[]>
*/
public List<String[]> transferArrayOfList(List<String> contentList){
List<String[]> contentLists =new ArrayList<>();
for(String content:contentList){
contentLists.add(content.split("\\s{1,}"));
}
return contentLists;
}
/**get result of reference by title
*
* @param head   data of  reference title
* @param title   reference title
* @param infos  data of each  reference
* @return  String result of reference by title ,if title is not matched ,return " "
*/
public String resolveValueByTagName(List<String> head,String[] infos,String title){
if(head.indexOf(title)>0){
return infos[head.indexOf(title)];
}
return "";
}
}
 五、测试
  这个小工具耗时2个周末终于搞定了,感谢大家的观看,写的不好或者欠缺考虑的地方请@我,谢谢各位老师。
  如果喜欢请点一下推荐哦,谢谢!
  源码地址:https://github.com/sunfan1988/sunfan
  六 将来的扩展
  1 把日志功能完善
  2 按照今后的需求把性能监控器逐个配置上去,基本上只要改一下controller和JSP页面就可以了。
  七、感谢帮助过我的人
  1 感谢张少能、朱际华、陈淼杰等小伙伴在我开发这个小工具过程中的指点,真的学到了很多。

posted on 2014-07-21 10:18 顺其自然EVO 阅读(2098) 评论(0)  编辑  收藏 所属分类: 测试学习专栏


只有注册用户登录后才能发表评论。


网站导航:
 
<2014年7月>
293012345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

常用链接

留言簿(55)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜