在Java中获取系统运行时间

8

我该如何确定计算机已经通电的时间(以毫秒为单位)?


3
这取决于操作系统,但你可能想要执行一个命令。 - mre
1
什么操作系统?没有外部第三方库或JNI,没法做到。 - Aniket Inge
请看链接:http://www.mkyong.com/java/how-do-get-time-in-milliseconds-in-java/ 这是关于Java中如何获取毫秒时间的内容。 - Rachel Gallen
1
@aniket 还要看平台是否需要外部库。在Linux上,您只需读取“/proc/uptime”文件即可。 - Anton Kovalenko
这取决于操作系统。对于Unix,您可以使用以下内容:https://dev59.com/2F3Va4cB1Zd3GeqPAnSU - Hari Menon
请参考https://dev59.com/EkbRa4cB1Zd3GeqP5fkU#674176。 - ameed
6个回答

14
在Windows中,您可以执行net stats srv命令,在Unix中,您可以执行uptime命令。必须解析每个输出以获取正常运行时间。该方法通过检测用户的操作系统自动执行所需的命令。
请注意,这两个操作都不会以毫秒精度返回正常运行时间。
public static long getSystemUptime() throws Exception {
    long uptime = -1;
    String os = System.getProperty("os.name").toLowerCase();
    if (os.contains("win")) {
        Process uptimeProc = Runtime.getRuntime().exec("net stats srv");
        BufferedReader in = new BufferedReader(new InputStreamReader(uptimeProc.getInputStream()));
        String line;
        while ((line = in.readLine()) != null) {
            if (line.startsWith("Statistics since")) {
                SimpleDateFormat format = new SimpleDateFormat("'Statistics since' MM/dd/yyyy hh:mm:ss a");
                Date boottime = format.parse(line);
                uptime = System.currentTimeMillis() - boottime.getTime();
                break;
            }
        }
    } else if (os.contains("mac") || os.contains("nix") || os.contains("nux") || os.contains("aix")) {
        Process uptimeProc = Runtime.getRuntime().exec("uptime");
        BufferedReader in = new BufferedReader(new InputStreamReader(uptimeProc.getInputStream()));
        String line = in.readLine();
        if (line != null) {
            Pattern parse = Pattern.compile("((\\d+) days,)? (\\d+):(\\d+)");
            Matcher matcher = parse.matcher(line);
            if (matcher.find()) {
                String _days = matcher.group(2);
                String _hours = matcher.group(3);
                String _minutes = matcher.group(4);
                int days = _days != null ? Integer.parseInt(_days) : 0;
                int hours = _hours != null ? Integer.parseInt(_hours) : 0;
                int minutes = _minutes != null ? Integer.parseInt(_minutes) : 0;
                uptime = (minutes * 60000) + (hours * 60000 * 60) + (days * 6000 * 60 * 24);
            }
        }
    }
    return uptime;
}

@KerrM 很抱歉没有早点注意到你的评论!在 Mac 上,第一小时的输出格式是什么?实际上,我完全根据文档编写了此方法的 OSX/Linux 部分,因为我很难访问这两种类型的操作系统。 - FThompson
@JavDev 目前正在期末考试中,但我给自己写了一个便条,在几天后回来看这个,因为现在我可以轻松访问 Linux 系统。一旦发生这种情况,我会再次联系你! - FThompson
2
将此答案投票否决,因为它只适用于Windows,如果您的操作系统语言和设置与建议的SimpleDateFormat中的内容匹配。如果更改了OS设置中的日期格式,则日期/时间模式将不匹配。同样的事情,如果您的OS语言不是英语,则“Statistics since”将以OS语言打印在net命令输出中,并且不会匹配。因此,该答案可能适用于您的计算机,但不适用于外国客户站点。 - jumar
@jumar 很好的观点。iTech的答案适用于其他语言吗? - FThompson
在Windows 10企业版上,我不得不将“net stats srv”更改为“net stats workstation”。 - daveloyall

9
使用OSHI库,它适用于Windows、Linux和Mac OS。你可以在这个链接中找到更多信息。
new SystemInfo().getOperatingSystem().getSystemUptime()

Windows,Linux和Mac OS以及FreeBSD和Solaris。;) - Daniel Widdis
@DanielWiddis 我不知道,谢谢。这让OSHI更加令人信服! - Stefan Reich

3
您可以使用OSHI库。以下是示例代码。
System.out.println("Uptime: "+FormatUtil.formatElapsedSecs(new oshi.SystemInfo().getOperatingSystem().getSystemUptime()));

为了让它正常工作,需要添加以下依赖项。
<dependency>
    <groupId>com.github.oshi</groupId>
    <artifactId>oshi-core</artifactId>
    <version>4.0.0</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna-platform</artifactId>
    <version>5.4.0</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.4.0</version>
</dependency>

2

对于Windows系统,您可以通过查询windows WMI来获得毫秒级别的uptime

要运行以下代码,您需要下载Jawin库,并将jawin.dll添加到您的eclipse项目根目录中。

 public static void main(String[] args) throws COMException {
    String computerName = "";
    String userName = "";
    String password = "";
    String namespace = "root/cimv2";

    String queryProcessor = "SELECT * FROM Win32_OperatingSystem";

    DispatchPtr dispatcher = null;

    try {

        ISWbemLocator locator = new ISWbemLocator(
                "WbemScripting.SWbemLocator");
        ISWbemServices wbemServices = locator.ConnectServer(computerName,
                namespace, userName, password, "", "", 0, dispatcher);
        ISWbemObjectSet wbemObjectSet = wbemServices.ExecQuery(
                queryProcessor, "WQL", 0, null);
        DispatchPtr[] results = new DispatchPtr[wbemObjectSet.getCount()];
        IUnknown unknown = wbemObjectSet.get_NewEnum();
        IEnumVariant enumVariant = (IEnumVariant) unknown
                .queryInterface(IEnumVariant.class);

        enumVariant.Next(wbemObjectSet.getCount(), results);

        for (int i = 0; i < results.length; i++) {
            ISWbemObject wbemObject = (ISWbemObject) results[i]
                    .queryInterface(ISWbemObject.class);

            System.out.println("Uptime: "
                    + wbemObject.get("LastBootUpTime"));
        }
    } catch (COMException e) {
        e.printStackTrace();
    }

2

我实在想不出一种与操作系统无关的解决方案。

一个选项是使用ManagementFactory.getRuntimeMXBean().getUptime();,它返回JVM的运行时间,虽然不完全符合你的需求,但已经是朝着正确方向迈出的一步。

你到底想用这些数据达到什么目的?


返回的数据类型是什么?我正在寻找系统登录时间,以便在我的应用程序中向用户发出警报,告知他们系统已经连续运行了几个小时。如果有任何更新,请更新代码。谢谢。 - akshaivk
@JavDev 返回以毫秒为单位的正常运行时间,类型为long。 - Simon Verhoeven

1

我希望找到一种不需要使用库的解决方案,使用WMIC是最适合我的。

private DateTime getSystemBootTime() throws IOException {
    String os = System.getProperty("os.name").toLowerCase();
    if (os.contains("win")) {
        Process uptimeProc = Runtime.getRuntime().exec("WMIC os get lastbootuptime");
        BufferedReader in = new BufferedReader(new InputStreamReader(uptimeProc.getInputStream()));
        String line = "";
        while ((line = in.readLine()) != null) {
            if (line.startsWith("ERROR")) {
                logger.error("CheckMachineUptime failed. WMIC operation failed. MACHINE OS: {} CMD output: {}", os, line);
                break;
            }
            if (line.startsWith("2")) {
                SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmss");
                try {
                    return new DateTime(format.parse(line));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }
        logger.error("Task failed! Could not identify time format. CMD OUTPUT: {}", in.readLine());
    } else logger.error("Task failed! Could not identify machine OS. MACHINE OS: {}", os);
    throw new RuntimeException("Getting uptime failed");
}

感谢FThompson和本帖的评论者们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接