在做Java项目时遇到对服务器性能做监控的需求,包括服务器内存使用,disk使用情况,cpu占用率等,使用Sigar便可以很好的解决这个问题。
Sigar简介
Sigar(System Information Gatherer And Reporter),开源的跨平台系统信息收集工具,C语言实现,下载点这儿,下载之后是个压缩包,其中包括各种平台,可通过程序判断自动切换。
如图所示,我们将sigar的各种库文件放到lib包下,编写工具类。
加载库文件
添加maven 依赖
<dependency>
<groupId>org.fusesource</groupId>
<artifactId>sigar</artifactId>
<version>1.6.4</version>
</dependency>
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class SigarLoader {
static boolean isLoad;
public String libpath;
static{
handleSigarDLL();
}
public static void handleSigarDLL(){
if(isLoad)return ;
/**
* 动态链接库所在的路径 在eclipse 是直接项目下/lib目录在实际项目中这个目录下的文件在拷到sigar.jar同级的目录并添下面的代码
*/
String lib=null;
String calzzlocation = SigarLoader.class.getProtectionDomain().getCodeSource().getLocation().getFile();
File clazzfile = new File(calzzlocation);
if(clazzfile.isDirectory()){
lib=clazzfile.getPath()+File.separator+"lib";
}else{
File jarfile = new File(calzzlocation);
String dir =jarfile.getParent();
lib=dir;
if(!existsDLL(dir)){
unzipJar(jarfile,dir);
}
}
String path = System.getProperty("java.library.path")+File.pathSeparator+lib;
//把动态链接库的路径加到path中
System.setProperty("java.library.path",path);
/**
* 动态链接库处理完成
*/
//System.out.println(path);
isLoad=true;
}
public static void unzipJar(File jarfile,String destDir){
try {
System.out.println("unziping dll files ...");
JarFile jar = new JarFile(jarfile);
Enumeration<JarEntry> entries= jar.entries();
while (entries.hasMoreElements()) {
// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
JarEntry entry = entries.nextElement();
String name = entry.getName();
File efile = new File(name);
//efile.get
if(name.startsWith("lib")&&!entry.isDirectory()){
//System.out.println(name+"=="+efile.getName());
//entry.
InputStream inp = jar.getInputStream(entry);
File dllfile= new File(destDir+File.separator+efile.getName());
FileOutputStream fos = new FileOutputStream(dllfile);
int len =0;
byte[] b =new byte[1024];
while((len =inp.read(b))>0){
fos.write(b,0, len);
}
inp.close();
fos.close();
dllfile.setLastModified(entry.getTime());
}
}
System.out.println("unzip dll files finished.");
} catch (IOException e) {
e.printStackTrace();
}
}
public static boolean existsDLL(String dir){
File file =new File(dir);
int count=0;
try{
for(File f: file.listFiles()){
if(f.getName().endsWith(".so")
||f.getName().endsWith(".dll")
){
count++;
}
}}catch(Exception e){
}
return count>0;
}
}
调用工具类
为了简单化处理,此处直接用json对服务器信息进行了包装,代码比较直观。
import java.net.InetAddress;
import org.hyperic.sigar.CpuPerc;
import org.hyperic.sigar.FileSystem;
import org.hyperic.sigar.FileSystemUsage;
import org.hyperic.sigar.Mem;
import org.hyperic.sigar.OperatingSystem;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public class MachineInfoServiceImpl {
public JSONObject getMachineInfo() {
JSONObject json = new JSONObject();
// 创建 sigar实例
Sigar sigar = new Sigar();
// 1.主机名
String hostname = "";
try {
hostname = InetAddress.getLocalHost().getHostName();
} catch (Exception exc) {
try {
hostname = sigar.getNetInfo().getHostName();
} catch (SigarException e) {
hostname = "localhost.unknown";
} finally {
sigar.close();
}
}
json.put("hostname", hostname);
// 2 .操作系统
OperatingSystem OS = OperatingSystem.getInstance();
String dataModal = OS.getDataModel();//
String description = OS.getDescription();
JSONObject osObj = new JSONObject();
osObj.put("description", description);
osObj.put("dataModal", dataModal);
json.put("os", osObj);
// 2. cpu
CpuPerc cpuList[] = null;
try {
cpuList = sigar.getCpuPercList();
} catch (SigarException e) {
e.printStackTrace();
}
JSONArray cupArray = new JSONArray();
for (int i = 0; i < cpuList.length; i++) {
JSONObject cpuObj = new JSONObject();
cpuObj.put("total", CpuPerc.format(cpuList[i].getCombined()));
cpuObj.put("idle", CpuPerc.format(cpuList[i].getIdle()));
cupArray.add(cpuObj);
}
json.put("cpuList", cupArray);
// 内存
Mem mem;
try {
mem = sigar.getMem();
JSONObject memObj = new JSONObject();
// 内存总量
memObj.put("total", mem.getTotal() / 1024L / 1024 + "M");
// 当前内存使用量
memObj.put("used", mem.getUsed() / 1024L / 1024 + "M");
json.put("memory", memObj);
} catch (SigarException e) {
e.printStackTrace();
}
// 磁盘
try {
FileSystem fslist[] = sigar.getFileSystemList();
JSONArray diskArray = new JSONArray();
for (int i = 0; i < fslist.length; i++) {
FileSystem fs = fslist[i];
// 分区的盘符名称
String diskName = fs.getDevName();
int type = fs.getType();
if (type == 2) {
FileSystemUsage usage = null;
try {
usage = sigar.getFileSystemUsage(fs.getDirName());
JSONObject diskObj = new JSONObject();
diskObj.put("diskName", diskName);
// 文件系统总大小
diskObj.put("total", usage.getTotal() / 1024 + "M");
// 文件系统已经使用量
diskObj.put("used", usage.getUsed() / 1024 + "M");
diskArray.add(diskObj);
} catch (SigarException e) {
e.printStackTrace();
}
}
}
json.put("diskList", diskArray);
} catch (SigarException e) {
e.printStackTrace();
}
return json;
}
}
调用
简单的打印服务器信息
SigarLoader.handleSigarDLL();
MachineInfoServiceImpl dd =new MachineInfoServiceImpl();
System.out.println(dd.getMachineInfo().toJSONString());
结果
打印结果显示了 cpu信息,disk磁盘使用信息,内存使用情况等。
{"cpuList":[{"total":"12.6%","idle":"87.4%"},{"total":"0.0%","idle":"100.0%"},{"total":"34.5%","idle":"65.4%"},{"total":"0.0%","idle":"100.0%"}],"os":{"dataModal":"64","description":"Microsoft Windows 7"},"diskList":[{"total":"102400M","diskName":"C:\\","used":"71179M"},{"total":"102401M","diskName":"D:\\","used":"67979M"},{"total":"122887M","diskName":"E:\\","used":"112624M"},{"total":"136638M","diskName":"G:\\","used":"46710M"}],"hostname":"***-PC","memory":{"total":"8120M","used":"5104M"}}
注: 网上看到有找不到库文件的情况,可用如下办法,比如将库文件放到//WebRoot/files/sigar 目录下
private static Sigar initSigar() {
try {
//此处只为得到依赖库文件的目录,可根据实际项目自定义
String file = Paths.get(PathKit.getWebRootPath(), "files", "sigar",".sigar_shellrc").toString();
File classPath = new File(file).getParentFile();
String path = System.getProperty("java.library.path");
String sigarLibPath = classPath.getCanonicalPath();
//为防止java.library.path重复加,此处判断了一下
if (!path.contains(sigarLibPath)) {
if (isOSWin()) {
path += ";" + sigarLibPath;
} else {
path += ":" + sigarLibPath;
}
System.setProperty("java.library.path", path);
}
return new Sigar();
} catch (Exception e) {
return null;
}
}