Linux僵尸进程没有被Java ProcessBuilder终止

问题描述

我有一个带有控制器的Java Spring REST API,该控制器运行带有ProcessBuilder类的linux命令

。该命令是生成的“查找”命令

问题是使用几天后,我在托管服务器中发现了许多未终止的进程。我不知道他们为什么还在那里而没有终结或被摧毁。 (我用ps -ef命令检查了

这是我的runcmd函数


public static final BufferedReader runcmd(String cmd) throws IOException,InterruptedException {
        ProcessBuilder processBuilder = new ProcessBuilder();
        processBuilder.command("bash","-c",cmd);

        processBuilder.redirectErrorStream(true);
        Process process = processBuilder.start();

        BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream()));

        int ret = process.waitFor();
        return output;
}

有没有办法确保不再剩下任何流程?

更新

问题仅来自具有非常大的输出流(标准输出)的命令。感谢提示@DuncG

由于此输出很重要,因此我不能忽略它。我必须找到一种消耗它的方法

关于如何使用可运行线程的任何想法?

谢谢

解决方法

您的命令会产生很多输出吗?造成僵尸的原因可能仅仅是cmd在STDOUT上写入了很多输出,并且流在BufferedReader中阻塞了。

您可以通过将重定向添加到null来测试是否是这种情况-只需在cmd的末尾附加“> / dev / null”即可。这会丢弃子流程的输出,这意味着BufferedReader不会充满未读取的数据/会阻塞子流程。

processBuilder.command("bash","-c",cmd+" > /dev/null");

如果这解决了僵尸问题,则可以还原重定向并使ProcessBuilder重定向输出到文件(在调用start()之前),或者您需要添加一个线程来消耗IO生成。

Path tmpdir = Path.of(System.getProperty("java.io.tmpdir"));
Path out = tmpdir.resolve("stdout.log");
processBuilder.redirectErrorStream(true);
processBuilder.redirectOutput(out.toFile());

最后,您应该返回out文件供呼叫者检查,或者可以返回Files.newBufferedReader(out)

如果您不使用上述重定向到文件,则会使用线程进行存储,以将输出捕获到内存缓冲区中。请注意,如果不重定向ERR-> OUT,您也需要复制STDERR:

Process p = pb.start();
ByteArrayOutputStream stdout = new ByteArrayOutputStream(8192);
new Thread(() -> copy(p.getInputStream(),stdout),"STDOUT").start();
int rc = p.waitFor();
byte[] sour = stdout.toByteArray()

使用方法:

private static void copy(InputStream in,OutputStream buf)
{
    try(var autoClose = in; var autoClose2 = buf)
    {
        in.transferTo(buf);
    }
    catch(IOException io)
    {
        throw new UncheckedIOException(io);
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...