/** * OSInfo.java * * Copyright 2012 Niolex, Inc. * * Niolex licenses this file to you under the Apache License, version 2.0 * (the "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package org.apache.niolex.commons.remote; import static org.apache.niolex.commons.codec.IntegerUtil.formatSize; import static org.apache.niolex.commons.remote.ConnectionWorker.endl; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryUsage; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Scanner; import org.apache.niolex.commons.codec.StringUtil; import org.apache.niolex.commons.test.SystemInfo; import org.apache.niolex.commons.util.Const; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Print the OS information into the command console for anyone who need it. * User application need to add an instance of this class into BeanServer * in order to have this functionality. * * @author <a href="mailto:xiejiyun@gmail.com">Xie, Jiyun</a> * @version 1.0.0 * @since 2012-7-28 */ public class OSInfo implements Invokable { private static final Logger LOG = LoggerFactory.getLogger(OSInfo.class); private static final int CPUTIME = 30; private SystemInfo systemInfo = SystemInfo.getInstance(); private String osName; private String osArch; private String osVersion; /** * Get the operating system information. Constructor */ public OSInfo() { super(); Properties props = System.getProperties(); // 获得系统属性集 osName = props.getProperty("os.name"); // 操作系统名称 osArch = props.getProperty("os.arch"); // 操作系统构架 osVersion = props.getProperty("os.version"); // 操作系统版本 } /** * This is the override of super method. * * @see org.apache.niolex.commons.remote.Invokable#invoke(java.io.OutputStream, java.lang.String[]) */ @Override public void invoke(OutputStream out, String[] args) throws IOException { final String endLine = endl(); StringBuilder sb = new StringBuilder(); sb.append("================").append(osName).append(' ').append(osArch); sb.append(" Version ").append(osVersion).append("================").append(endLine); systemInfo.refreshSystemInfo(); // Cat 1. Memory. sb.append("1. Memory Info:").append(endLine); // Next is Linux memory info and disk info, windows if ignored. String[] cmsArr = null; if (osName.toLowerCase().startsWith("win")) { // } else { cmsArr = getLinuxCpuAndMemInfo(); } if (cmsArr != null) { sb.append(" ").append(cmsArr[1]).append(endLine); sb.append(" ").append(cmsArr[2]).append(endLine); } MemoryUsage heapMem = systemInfo.getHeapMem(); long freeMem = heapMem.getCommitted() - heapMem.getUsed(); sb.append(String.format(" JVM %-8s Total %7sB, Used %7sB, Free %7sB", "Heap", formatSize(heapMem.getCommitted()), formatSize(heapMem.getUsed()), formatSize(freeMem))); sb.append(endLine); MemoryUsage nonHeap = systemInfo.getNonHeapMem(); freeMem = nonHeap.getCommitted() - nonHeap.getUsed(); sb.append(String.format(" JVM %-8s Total %7sB, Used %7sB, Free %7sB", "Non-Heap", formatSize(nonHeap.getCommitted()), formatSize(nonHeap.getUsed()), formatSize(freeMem))); sb.append(endLine); // Cat 2. GC. sb.append(endLine).append("2. GC Info:").append(endLine); List<GarbageCollectorMXBean> gcList = ManagementFactory.getGarbageCollectorMXBeans(); for (GarbageCollectorMXBean bean : gcList) { sb.append(String.format(" %-20s Collection Count %4d, Time %6dms", bean.getName() + " GC", bean.getCollectionCount(), bean.getCollectionTime())); sb.append(endLine); } // Cat 3. CPU. sb.append(endLine).append("3. CPU Info:").append(endLine); if (osName.toLowerCase().startsWith("win")) { int retn = getWindowsCpuIdle(); sb.append(" CPU Number ").append(systemInfo.getCpuNumber()); sb.append(" Idle ").append(formatPercent(retn)).append(endLine); } else if (cmsArr != null) { // We just think it's Linux. sb.append(" ").append(cmsArr[0]).append(endLine); sb.append(" Load Average ").append(systemInfo.getLoadAverage()).append(endLine); } // Cat 4. Disk. sb.append(endLine).append("4. Disk Info:").append(endLine); final long gSize = Const.G; if (osName.toLowerCase().startsWith("win")) { File[] roots = File.listRoots();// 获取磁盘分区列表 for (int i = 0; i < roots.length; i++) { File root = roots[i]; long free = root.getFreeSpace() / gSize; long total = root.getTotalSpace() / gSize; long usable = root.getUsableSpace() / gSize; long usePer = total == 0 ? 0 : (total - free) * 100 / total; sb.append(" [").append(root).append("]:"); sb.append(String.format(" Total %5dG, Usable %5dG, Used %2d%%", total, usable, usePer)); sb.append(endLine); } } else { List<String> list = getLinuxDiskInfo(); for (String s : list) { sb.append(" ").append(s).append(endLine); } } // Cat 5. Threads. sb.append(endLine).append("5. Threads Info:").append(endLine); sb.append(" Total Threads ").append(systemInfo.getTotalThreadCount()); sb.append(", Active ").append(systemInfo.getActiveThreadCount()).append(endLine); // At the end. out.write(StringUtil.strToUtf8Byte(sb.toString())); } /** * Format integer into percent format. * * @param k the integer to be formatted * @return the percent in string format */ public String formatPercent(int k) { return k / 100 + "." + k % 100 + "%"; } /** * Get the windows CPU idle time. * * @return the percent of CPI idle time */ public int getWindowsCpuIdle() { try { String procCmd = "wmic.exe process get Caption, KernelModeTime, UserModeTime"; // 取进程信息 long[] c0 = getWindowsCPUTime(Runtime.getRuntime().exec(procCmd)); Thread.sleep(CPUTIME); long[] c1 = getWindowsCPUTime(Runtime.getRuntime().exec(procCmd)); long total = c1[0] - c0[0]; long idle = c1[1] - c0[1]; return (int) (idle * 10000 / total); } catch (Exception e) { LOG.error("Failed to get windows CPU idle.", e); return -1; } } /** * Get windows CPU time. * * @param proc the process * @return CPU status */ public long[] getWindowsCPUTime(final Process proc) { long[] retn = new long[2]; Scanner scan = null; try { proc.getOutputStream().close(); scan = new Scanner(proc.getInputStream()); String line = scan.nextLine(); int nameIdx = line.indexOf("Caption"); int kmtIdx = line.indexOf("KernelModeTime"); int umtIdx = line.indexOf("UserModeTime"); long idleTime = 0; long totalTime = 0; while (scan.hasNextLine()) { line = scan.nextLine(); if (line.isEmpty()) { continue; } String name = line.substring(nameIdx, kmtIdx - 1).trim(); if (name.equalsIgnoreCase("WMIC.exe")) { continue; } long curTime = Long.parseLong(line.substring(kmtIdx, umtIdx - 1).trim()) + Long.parseLong(line.substring(umtIdx).trim()); if (name.equalsIgnoreCase("System Idle Process") || name.equalsIgnoreCase("System")) { idleTime += curTime; } totalTime += curTime; } retn[0] = totalTime; retn[1] = idleTime; } catch (Exception e) { LOG.error("Failed to get windows CPU time.", e); } finally { if (scan != null) { scan.close(); } } return retn; } /** * Get Linux CPU Info, Memory Info, and Swap Info all at the same time. * * @return the information from top result */ public String[] getLinuxCpuAndMemInfo() { Scanner scan = null; try { Process process = Runtime.getRuntime().exec("top -b -n 1"); process.getOutputStream().close(); scan = new Scanner(process.getInputStream()); if (osVersion.equals("2.4")) { scan.nextLine(); scan.nextLine(); scan.nextLine(); scan.nextLine(); return new String[] {scan.nextLine(), scan.nextLine(), scan.nextLine()}; } else { scan.nextLine(); scan.nextLine(); return new String[] {scan.nextLine(), scan.nextLine(), scan.nextLine()}; } } catch (IOException ioe) { return null; } finally { if (scan != null) { scan.close(); } } } /** * Get the Linux disk free information. * * @return the result from "df -h" */ public List<String> getLinuxDiskInfo() { Scanner scan = null; try { Process process = Runtime.getRuntime().exec("df -h"); process.getOutputStream().close(); scan = new Scanner(process.getInputStream()); List<String> list = new ArrayList<String>(); while (scan.hasNext()) { list.add(scan.nextLine()); } return list; } catch (IOException ioe) { return null; } finally { if (scan != null) { scan.close(); } } } public SystemInfo getSystemInfo() { return systemInfo; } public String getOsName() { return osName; } public String getOsArch() { return osArch; } public String getOsVersion() { return osVersion; } }