java Runtime.getRuntime().exec()学习

发布于:2025-01-22 ⋅ 阅读:(13) ⋅ 点赞:(0)

以前的一个需求中涉及到java里执行一个python脚本,当时使用了

Runtime.getRuntime().exec(”python xx.py“)

后面也没啥事,有一天就发现这里出问题了。下面来说下。

Runtime.getRuntime().exec(”python xx.py“) 这个知道会起一个线程去执行python脚本,但是执行过程中的日志,以及你等待这个脚本的执行时间是否有考虑?

1.py脚本如果执行时间较长怎么办 程序继续等待还是跳过还是kill线程

2.py脚本如果执行时间较长怎么办,日志如何打印?

下面来介绍几个简单的demo来学习下。

首先我们知道ping www.baidu.com 这个cmd命令大概时间是3s 然后日志是一行一行输出的。

demo1 最简单的执行命令,输出日志,结束

    /**
     *current time is 2025-01-21 14:59:14:875
     * ping 输出内容(一次性)
     *current time is 2025-01-21 14:59:18:080
     */
    @Test
    public void testProcess2() throws IOException, InterruptedException {
        runCommand(command);
        InputStream errorStream = p.getErrorStream();
        InputStream inputStream = p.getInputStream();
        System.out.println(convertStream2String(errorStream));
        System.out.println(convertStream2String(inputStream));
        printCurrent();
    }

demo2 已知ping baidu 是3s完成,那有时候脚本执行比较慢 一直卡住呢?我们java任务不可能一直等待吧

   /**
     * current time is 2025-01-21 15:21:49:776
     * current time is 2025-01-21 15:21:51:799
     * ping 输出内容(一次性)
     * current time is 2025-01-21 15:21:52:986
     * 花费时间3s
     */
    @Test
    public void testProcess3() throws IOException, InterruptedException {
        runCommand(command);
        p.waitFor(2,TimeUnit.SECONDS); // 等待2s
        printCurrent();
        System.out.println(convertStream2String(p.getErrorStream()));
        System.out.println(convertStream2String(p.getInputStream()));
        printCurrent();
    }

//可以看到确实是等待了2s,但是还是3s之后输出任务日志,和我们预想的不一样

demo3 如何解决demo2的问题呢?我们等待了2s 但是线程并没有停止,还是继续执行,p.get还是的等待任务的输入。

/**
     *current time is 2025-01-21 15:44:32:883
     * current time is 2025-01-21 15:44:34:911--刚好2s
     * ping 输出内容(一部分)
     *current time is 2025-01-21 15:44:34:914 --刚好2s
     */
    @Test
    public void testProcess4() throws IOException, InterruptedException {
        runCommand(command);
        p.waitFor(2,TimeUnit.SECONDS);
        p.destroy();

        printCurrent();
        System.out.println(convertStream2String(p.getErrorStream()));
        System.out.println(convertStream2String(p.getInputStream()));
        printCurrent();
    } 

//这里在等待2s后,强制将线程干掉,此时p结束获取输入

这时候又有一个问题了? 我们在cmd的时候看到的日志都是一行一行的输出,这里的日志都是整体输出的,不一样呀?

    /**
     * current time is 2025-01-21 15:55:04:903
     * current time is 2025-01-21 15:55:04:917
     * 2025-01-21 15:55:05:049-success:
     * 2025-01-21 15:55:05:049-success:正在 Ping www.a.shifen.com [183.2.172.185] 具有 32 字节的数据:
     * 2025-01-21 15:55:05:058-success:来自 183.2.172.185 的回复: 字节=32 时间=9ms TTL=45
     * 2025-01-21 15:55:06:065-success:来自 183.2.172.185 的回复: 字节=32 时间=9ms TTL=45
     * current time is 2025-01-21 15:55:06:926
     */
    @Test
    public void testProcess5() throws InterruptedException {
        runCommand(command);
        InputStream inputStream = p.getInputStream();
        startPrintThread(inputStream, "success");
        InputStream errorStream = p.getErrorStream();
        startPrintThread(errorStream, "error");
        printCurrent();
        p.waitFor(2L, TimeUnit.SECONDS);
        p.destroy();
        printCurrent();
    }

//可以看到日志是一行行的输出且只输出了2s

其实主要问题就在于 脚本任务执行时间比如一般时间为3s 但是偶尔异常情况会有5s 10s

那么到了3s后你期望怎么?

1.获取3s内的所有打印日志,返回一个失败结果

2.获取3s内的所有打印日志,让任务继续执行

3. 3s内的日志逐行打印