java远程监控服务器内存、磁盘、交换空间、cpu的使用率问题

这篇博客介绍如何使用Java远程监控Linux服务器的内存、磁盘、交换空间和CPU使用率。通过封装Linux命令执行并处理返回信息,实现监控功能。文章提供了核心代码示例,包括LinuxConnect和MonitorInfor类,以及处理时间转换的方法。读者需要注意不同服务器返回信息的格式差异,并自行调试以适应自己的需求。
摘要由CSDN通过智能技术生成

前台的效果图:
在这里插入图片描述

后台代码:
我将远程服务器的连接、关闭与命令处理,因项目中多次的调用,规到一个类中。
LinuxConnect中有多个LinuxConnect方便自己注意区别;后面还有一篇;服务器程序管理的功能;
LinuxConnect.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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

public class LinuxConnect {
	
	 public static final String LINE_SEPARATOR = System.getProperty("line.separator");
	 private static Session session;
	 static BufferedReader reader = null;
     static Channel channel = null;
	
	  /**
     * 连接到指定的HOST
     *
     * @return isConnect
     * @throws JSchException JSchException
     */
    public static boolean connect(String user, String passwd, String host) {
        JSch jsch = new JSch();
        try {
            session = jsch.getSession(user, host, 22);
            session.setPassword(passwd);

            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();
        } catch (JSchException e) {
            e.printStackTrace();
            System.out.println(host+"connect error !");
            return false;
        }
        return true;
    }
    
    /**
     * 远程连接Linux 服务器 执行相关的命令
     *
     * @param commands 执行的脚本
     * @param user     远程连接的用户名
     * @param passwd   远程连接的密码
     * @param host     远程连接的主机IP
     * @return 最终命令返回信息
     */
    public static Map<String, String> runDistanceShell(String[] commands) {
        
        Map<String, String> map = new HashMap<>();
        StringBuilder stringBuffer;

        
        try {
            for (String command : commands) {
                stringBuffer = new StringBuilder();
                channel = session.openChannel("exec");
                ((ChannelExec) channel).setCommand(command);

                channel.setInputStream(null);
                ((ChannelExec) channel).setErrStream(System.err);

                channel.connect();
                InputStream in = channel.getInputStream();
                reader = new BufferedReader(new InputStreamReader(in));
                String buf;
                while ((buf = reader.readLine()) != null) {

                    //舍弃PID 进程信息
//                    if (buf.contains("PID")) {
//                        break;
//                    }
                    stringBuffer.append(buf.trim()).append(LINE_SEPARATOR);
                }
                channel.disconnect();
                //每个命令存储自己返回数据-用于后续对返回数据进行处理
              
                map.put(command, stringBuffer.toString());
            }
        } catch (IOException | JSchException e) {
            e.printStackTrace();
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (channel != null) {
                channel.disconnect();
            }
            session.disconnect();
        }
        return map;
    }
    /**
     * 远程连接Linux 服务器 执行相关的命令
     *
     * @param command 执行的脚本
     * @param user     远程连接的用户名
     * @param passwd   远程连接的密码
     * @param host     远程连接的主机IP
     * @return 最终命令返回信息
     */
    public static Map<String, String> runDistanceShell(String command) {
        
        Map<String, String> map = new HashMap<>();
        StringBuilder stringBuffer;

        
        try {
           
                stringBuffer = new StringBuilder();
                channel = session.openChannel("exec");
                ((ChannelExec) channel).setCommand(command);

                channel.setInputStream(null);
                ((ChannelExec) channel).setErrStream(System.err);

                channel.connect();
                InputStream in = channel.getInputStream();
                reader = new BufferedReader(new InputStreamReader(in));
                String buf;
                while ((buf = reader.readLine()) != null) {

                    //舍弃PID 进程信息
                    if (buf.contains("PID")) {
                        break;
                    }
                    stringBuffer.append(buf.trim()).append(LINE_SEPARATOR);
                }
                channel.disconnect();
                //每个命令存储自己返回数据-用于后续对返回数据进行处理

                map.put(command, stringBuffer.toString());
            
        } catch (IOException | JSchException e) {
            e.printStackTrace();
        } finally {
           
        }
        return map;
    }
    
    /**
     * 直接在本地执行 shell
     *
     * @param commands 执行的脚本
     * @return 执行结果信息
     */
    public static Map<String, String> runLocalShell(String[] commands) {
        Runtime runtime = Runtime.getRuntime();

        Map<String, String> map = new HashMap<>();
        StringBuilder stringBuffer;

        BufferedReader reader;
        Process process;
        for (String command : commands) {
            stringBuffer = new StringBuilder();
            try {
                process = runtime.exec(command);
                InputStream inputStream = process.getInputStream();
                reader = new BufferedReader(new InputStreamReader(inputStream));
                String buf;
                while ((buf = reader.readLine()) != null) {
                    //舍弃PID 进程信息
                    if (buf.contains("PID")) {
                        break;
                    }
                    stringBuffer.append(buf.trim()).append(LINE_SEPARATOR);
                }

            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
            //每个命令存储自己返回数据-用于后续对返回数据进行处理
            map.put(command, stringBuffer.toString());
        }
        return map;
    }
    public  boolean judgeString(String str) {
   	 Pattern pattern = Pattern.compile("-?[0-9]+\\.?[0-9]*");
       Matcher isNum = pattern.matcher(str);
       if (!isNum.matches()) {
      	 return false;
       }else {
      	 return true;		
       }
   }
    
    public void close() {
    	 try {
             if (reader != null) {
                 reader.close();
             }
         } catch (IOException e) {
             e.printStackTrace();
         }
         if (channel != null) {
             channel.disconnect();
         }
         session.disconnect();
    }

	

}

这里为方便定义了一个实体类:
MonitorInfor.java
各位自己get与set下

	private Integer id;
	private String ip;//服务器IP
	private String useName;//服务登录名
	private String password;//服务登录密码
	private static final double cpuTotal=100;//cpu总计
	private double cpuFree;//cpu空闲率
	private double cpuUS;//cpu使用率
	private double ramUS;//内存使用率
	private double swapUS;//交换空间使用率
	private double diskUS;//磁盘空间使用率
	private double ramTotal;//内存总空间
	private double swapTotal;//交换空间总空间
	private double diskTotal;//磁盘空间总空间
	private double ramFree;//内存空闲空间
	private double swapFree;//交换空间空闲空间
	private double diskFree;//磁盘空间空间
	private double ramUser;//内存已使用空间
	private double swapUser;//交换空间已使用空间
	private double diskUser;//磁盘已使用空间
	private String UpdateTime;//服务器资源监控刷新时间
	private String programName;//程序名称
	private String programPath;//程序部署路径
	private String ProcessNumber;//程序进程
	private String programType;//程序状态
	private String line;

核心代码,执行linux命令得到返回集;并对信息进行处理;可能各位执行后会得不到数据,请你各位使用debug执行;看命令执行后是否有返回信息;如果有再看处理过程遇到的问题;因服务器不同返回的信息格式会有差异。
LinuxStateForShell.java

核心我是从这文章复制进行测试修改成的:https://www.cnblogs.com/longronglang/p/6936318.html

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.Dao.MonitorInfor;
import com.util.DateTimeUtil;

public class LinuxStateForShell {
	 public static final String CPU_MEM_SHELL = "top -b -n 1";
	    public static final String FILES_SHELL = "df -hl";
	    public static final String[] COMMANDS = {CPU_MEM_SHELL,FILES_SHELL};
	    
	   
	   
	    
	    public static LinuxConnect conn= new LinuxConnect();
	   

	    /**
	     * 处理 shell 返回的信息
	     * 具体处理过程以服务器返回数据格式为准
	     * 不同的Linux 版本返回信息格式不同
	     * @param result shell 返回的信
	     * @return 终处理后的信息
	     */
	    private static MonitorInfor disposeResultMessage(Map<String, String> result) {

	        StringBuilder buffer = new StringBuilder();
	        MonitorInfor monitorInfor=new  MonitorInfor();
	        for (String command : COMMANDS) {
	            String commandResult = result.get(command);
	            if (null == commandResult) continue;
	            if (command.equals(CPU_MEM_SHELL)) {
	                String[] strings = commandResult.split(conn.LINE_SEPARATOR);
	                //将返回结果按换行符分
	                for (String line : strings) {
	                    line = line.toUpperCase();//转大写处

	                    //处理CPU Cpu(s): 10.8%us,  0.9%sy,  0.0%ni, 87.6%id,  0.7%wa,  0.0%hi,  0.0%si,  0.0%st
	                    if (line.startsWith("%CPU(S):")) {
	                        String cpuStr = "CPU 用户使用占有:";
	                        try {
	                             cpuStr += line.split(":")[1].split(",")[0].replace("US", "");
	                            monitorInfor.setCpuUS(Double.valueOf(cpuStr.split(":")[1].trim()));
	                        } catch (Exception e) {
	                            e.printStackTrace();
	                            cpuStr += "计算过程出错";
	                        }
	                        buffer.append(cpuStr).append(conn.LINE_SEPARATOR);

	                        //处理内存KIB MEM : 32379960 TOTAL, 22603716  free,  7298292 used,  2477952 BUFF/CACHE
	                    } else if (line.startsWith("KIB MEM")) {
	                        String memStr ;
	                        try {
//	                            memStr += line.split(":")[1]
//	                                    .replace("TOTAL", "总计")
//	                                    .replace("FREE", "空闲")
//	                                    .replace("USED", "已使�?")
//	                                    .replace("BUFF/CACHE", "缓存");
	                        	  memStr = line.split(":")[1]
		                                    .replace("TOTAL", "")
		                                    .replace("FREE", "")
		                                    .replace("USED", "")
		                                    .replace("BUFF/CACHE", "");
	                        	 String[] meminfor=dataExtract(memStr);
	                        	 for(int i=0;i<meminfor.length;i++) {
	                        		 meminfor[i]+="K";
	                        		 disposeUnit(meminfor[i]);
	                        	 }
	                        	 monitorInfor.setRamTotal(decimalFromat(disposeUnit(meminfor[0])));
	                        	 monitorInfor.setRamFree(decimalFromat(disposeUnit(meminfor[1])));
	                        	 monitorInfor.setRamUser(decimalFromat(disposeUnit(meminfor[2])));
	                        	 monitorInfor.setRamUS(decimalFromat((monitorInfor.getRamUser()/monitorInfor.getRamTotal())*100));
	                        } catch (Exception e) {
	                            e.printStackTrace();
	                            memStr = "计算过程出错";
	                            buffer.append(memStr).append(conn.LINE_SEPARATOR);
	                            continue;
	                        }
	                        buffer.append(memStr).append(conn.LINE_SEPARATOR);
	                        //交换空间 KiB Swap: 16318460 total, 16318460 free,        0 used. 24519440 avail Mem
	                    }else if(line.startsWith("KIB SWAP")) {
	                    	 String swapStr;
		                        try {
//		                        	swapStr += line.split(":")[1]
//		                                    .replace("TOTAL", "总计")
//		                                    .replace("FREE", "空闲")
//		                                    .replace("USED", "已使�?")
//		                                    .replace(".", ",")
//		                                    .replace("AVAIL MEM", "缓存");
		                        	swapStr = line.split(":")[1]
		                                    .replace("TOTAL", "")
		                                    .replace("FREE", "")
		                                    .replace("USED", "")
		                                    .replace(".", ",")
		                                    .replace("AVAIL MEM", "");
		                        	 String[] swapinfor=dataExtract(swapStr);
		                        	 for(int j=0;j<swapinfor.length;j++) {
		                        		 swapinfor[j]+="K";
		                        		 swapinfor[j]=String.valueOf(disposeUnit(swapinfor[j]));
		                        	 }
		                        	 monitorInfor.setSwapTotal(changeDouble(swapinfor[0]));
		                        	 monitorInfor.setSwapFree(changeDouble(swapinfor[1]));
		                        	 monitorInfor.setSwapUser(changeDouble(swapinfor[2]));
		                        	 monitorInfor.setSwapUS(decimalFromat((monitorInfor.getSwapUser()/monitorInfor.getSwapTotal())*100));
		                        	  

		                        } catch (Exception e) {
		                            e.printStackTrace();
		                            swapStr = "计算过程出错";
		                            buffer.append(swapStr).append(conn.LINE_SEPARATOR);
		                            continue;
		                        }
		                        buffer.append(swapStr).append(conn.LINE_SEPARATOR);
	    	            }
	                }
	            } else if (command.equals(FILES_SHELL)) {
	                //处理系统磁盘状�??
	                buffer.append("系统磁盘状�??:");
	                String disk;
	                try {
	                	 disk=disposeFilesSystem(commandResult).toString();
	                	 disk=disk.split(":")[1]
                                 .replace("总计", "")
                                 .replace("已使�?", "")
                                 .replace("空闲", "");
	                	String[] disklist =dataExtract(disk);
	                	monitorInfor.setDiskTotal(changeDouble(disklist[0]));
	                	monitorInfor.setDiskUser(changeDouble(disklist[1]));
	                	monitorInfor.setDiskFree(changeDouble(disklist[2]));
	                	monitorInfor.setDiskUS(decimalFromat((monitorInfor.getDiskUser()/monitorInfor.getDiskTotal())*100));
	                	
	                    buffer.append(disposeFilesSystem(commandResult)).append(conn.LINE_SEPARATOR);
	                    System.out.println("打印磁盘�?"+disposeFilesSystem(commandResult));
	                } catch (Exception e) {
	                    e.printStackTrace();
	                    disk="计算过程出错";
	                    buffer.append(disk).append(conn.LINE_SEPARATOR);
	                }
	            }
	        }

	        return monitorInfor;
	    }

	    //处理系统磁盘状�??

	    /**
	     * Filesystem            Size  Used Avail Use% Mounted on
	     * /dev/sda3             442G  327G   93G  78% /
	     * tmpfs                  32G     0   32G   0% /dev/shm
	     * /dev/sda1             788M   60M  689M   8% /boot
	     * /dev/md0              1.9T  483G  1.4T  26% /ezsonar
	     *
	     * @param commandResult 处理系统磁盘状�?�shell执行结果
	     * @return 处理后的结果
	     */
	    private static String disposeFilesSystem(String commandResult) {
	        String[] strings = commandResult.split(conn.LINE_SEPARATOR);

	        // final String PATTERN_TEMPLATE = "([a-zA-Z0-9%_/]*)\\s";
	        double  size = 0;
	        double  used = 0;
	        for (int i = 0; i < strings.length; i++) {
	            if (i == 0) continue;
	            int temp = 0;
	            int n=0;
	            String old = null;
	            int oldIndex=0;
	            int number=0;
	            for (String s : strings[i].split("\\b")) {
	            	n++;
	                String lastIndex = s.substring(s.length() - 1);
	                String num =  s.substring(0,s.length() - 1);
	                num=num.trim();
	                if((s.length()==1&&conn.judgeString(lastIndex))||(s.length()==1&&s.equals("."))||(n-oldIndex==1&&oldIndex>0)) {
	                	
	                	if(conn.judgeString(s)) {
	                		old=s;
	                		oldIndex=n;
	                		continue;
	                	}
	                	 if(s.equals(".")&&(n-oldIndex==1)) {
	                		 old+=s;
	                		 oldIndex=n;
	                		 continue;
	                	 }
	                	 String end = s.substring(s.length() - 1);
	                	 if((end.equals("G")||end.equals("T")||end.equals("M")||end.equals("K")||end.equals("KM"))&&(n-oldIndex==1)) {
	                		 old+=s;
	                		 num=old.substring(0,old.length() - 1);
	                		 s=old;
	                	 }else {
	                		 old=null;
	                		 oldIndex=0;
	                		 temp++;
	                	 }
	                	}else if(oldIndex>0&&num.equals("")) {
	                		 old=null;
	                		 oldIndex=0;
	                		 temp++;
	                	} 


	                if (!conn.judgeString(num)) {
	                	continue;
	                }else {
	                	
	                		 if (!s.trim().isEmpty()) {
	                			 ++temp;
	 	  	                    if (temp == 1) {
	 	  	                        size += disposeUnit(s);
	 	  	                    }else if (temp == 2){
	 	  	                        used += disposeUnit(s);
	 	  	                    }
	 	  	                } 
	                }
	            }
	        }
	        return new StringBuilder().append("系统磁盘使用情况:").append("总计 ").append(size).append(", 已使�?").append(used).append(",空闲")
	                .append(size - used).toString();
//	        return new StringBuilder().append("系统磁盘使用情况:").append("总计 ").append(size).append("G , 已使�?").append(used).append("G ,空闲")
//	                .append(size - used).append("G").toString();
	    }
	 

	    /**
	     * 处理单位转换
	     * K/KB/M/T �?终转换为G 处理
	     *
	     * @param s 带单位的数据字符�?
	     * @return 以G 为单位处理后的数�?
	     */
	    private static double disposeUnit(String s) {

	        try {
	            s = s.toUpperCase();
	            String lastIndex = s.substring(s.length() - 1);
	            String num = s.substring(0, s.length() - 1);
	            double parseInt = Double.parseDouble(num);
	            if (lastIndex.equals("G")) {
	                return parseInt;
	            } else if (lastIndex.equals("T")) {
	                return parseInt * 1024;
	            } else if (lastIndex.equals("M")) {
	                return parseInt / 1024;
	            } else if (lastIndex.equals("K") || lastIndex.equals("KB")) {
	                return parseInt / (1024 * 1024);
	            }
	        } catch (NumberFormatException e) {
	            e.printStackTrace();
	            return 0;
	        }
	        return 0;
	    }
	    public static String[] dataExtract(String str){
	    	        MonitorInfor monitor =new MonitorInfor();
	    			String[] datainfor=str.split(",");
	    			for(int i=0;i<datainfor.length;i++) {
	    				datainfor[i]=datainfor[i].trim();
	    			}
			return datainfor;	
	    }
	   
	    public static double decimalFromat(double s) {
	    	 BigDecimal bg = new BigDecimal(s);
	    	    double d3 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
			return d3;
	    }
	    
	    public static List<MonitorInfor> getData(List<MonitorInfor> Infor){
	    	List<MonitorInfor> MonitorInforList =new ArrayList<MonitorInfor>();
	    	for(int i=0;i<Infor.size();i++) {
	    		if(conn.connect(Infor.get(i).getUseName(),Infor.get(i).getPassword(),Infor.get(i).getIp()))
	    		{
	    			 Map<String, String> result = conn.runDistanceShell(COMMANDS);
		    		  MonitorInfor monitor=disposeResultMessage(result);
		    		  monitor.setIp(Infor.get(i).getIp());
		    		  monitor.setUpdateTime(DateTimeUtil.getDateToString(System.currentTimeMillis()));
		    		  MonitorInforList.add(monitor);
	    		}else {
	    			continue;
	    		}	 
	    	}
//	    	H2ReadUpdata h2=new H2ReadUpdata();
//	    	h2.updata(MonitorInforList);
			return MonitorInforList;	
	    }
	    
	    public static double changeDouble(String s) {
	    	
	    	return decimalFromat(Double.valueOf(s));
	    }
	    
	    public static String changeString(Double s) {
	    	return String.valueOf(s);
	    }

	    public static void main(String[] args) {
	    	if(conn.connect("用户", "密码", "ip地址")){ 
	    		Map<String, String> result = conn.runDistanceShell(COMMANDS);
	        MonitorInfor monitor=disposeResultMessage(result);
	        System.out.println(monitor.toString());	
    		}else {
    			System.out.println("连接不上");
    		}
	      
	    }


}

核心代码中还调用了一个我自己做的时间转换的类:

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;


/**
 * @author yangxin-ryan
 */
public class DateTimeUtil {

    public static Long parse(String startTime, String timeFormat){
       SimpleDateFormat sdf = new SimpleDateFormat(timeFormat);
        Date date = null;
        try {
            date = sdf.parse(startTime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date.getTime();

    }

    public static String format(Date datetime, String retTimeFmt) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(retTimeFmt);
        String date = simpleDateFormat.format(datetime);
        return Timestamp.valueOf(date).toString();
    }
    //时间戳转时间类型
    public static String getDateToString(long time) {
        Date d = new Date(time);
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sf.format(d);
   }
    //时间类型转时间戳
    public static long getStringToDate(String time) {
    	SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    	         Date date = new Date();
    	             try {
						date = sf.parse(time);
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
    	         
    	         return date.getTime();
    	     }
}

后面看各位自己调试了。只能帮到这了。

评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

绅士的燕尾服

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值