Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 侦听Runtime.exec()事件_Java_Kotlin_Process - Fatal编程技术网

Java 侦听Runtime.exec()事件

Java 侦听Runtime.exec()事件,java,kotlin,process,Java,Kotlin,Process,我有一个函数,它使用以下代码作为命令执行字符串: fun String.runAsCommand() : String { val process = Runtime.getRuntime().exec(this) if (!process.waitFor(60, TimeUnit.SECONDS)) { process.destroy() throw RuntimeException("execution timed out: $this")

我有一个函数,它使用以下代码作为命令执行字符串:

fun String.runAsCommand() : String {
    val process = Runtime.getRuntime().exec(this)
    if (!process.waitFor(60, TimeUnit.SECONDS)) {
        process.destroy()
        throw RuntimeException("execution timed out: $this")
    }
    if (process.exitValue() != 0) {
        throw RuntimeException("execution failed with code ${process.exitValue()}: $this")
    }

    return process.inputStream.bufferedReader().readText()
}

但是,完成所有操作后,此代码将输出命令输出。但所讨论的过程实际上是一个长过程,需要长达40秒,并逐渐将状态输出到控制台。如何使用某种侦听器构造截获这些echo/控制台日志?

标准方法是使用,然后启动另一个线程读取进程的stdout(这是您的输入)

我不确定这是否是最好的方法,但这里有一些代码,我想出了做一些非常类似的事情(在我的例子中,进程写入了它的stdout和stderr,所以我需要同时读取它们——但在进程完成之前我不需要看到它们。我还需要返回进程的退出状态以及这两个状态,并处理超时。不过,我不需要向进程的stdin发送任何内容;如果需要,您必须这样做扩展它。)


这不起作用,一旦完成了整个过程,它仍然会输出过程的结果。正如我所说,我的代码正在做类似的事情——可能并不完全是你想要的。(虽然你没有给出任何细节,所以很难确定。)但是这应该说明了一般的想法,也许你可以看到你如何适应StreamReader。在挖掘之后,我认为这是一个实际命令的问题。它是一个C++程序,调用PROTFF()代替PROTLLN()。本身不一定是个问题-过去总是这样做的。但是
stdout
通常是行缓冲的,所以如果这些调用不包括
\n
行分隔符,那么它可能不会是
flush()
ing流,并且部分或全部输出可能会被卡在该进程内的缓冲区中,并且对Kotlin程序不可用。(您可以尝试将其输出重定向到stderr,这通常是无缓冲的,但我不知道是否可行。)嗯,这很奇怪,因为printf()是否在语句结尾包含一个\n
/**
* Runs a system command and captures its output (and stderr).
*
* @param command The program name and any arguments.
* @param workingDir The working directory of the process, or `null` for the same as this process.
* @param timeoutSecs Maximum time to wait for it to finish, in seconds.  (Default is 5 mins.)
* @param throwOnFailure Whether to throw a [ProcessFailedException] if it returns a non-zero exit value.
* @throws IndexOutOfBoundsException if the command is empty.
* @throws SecurityException if a security manager prevented creation of the process or a redirection.
* @throws UnsupportedOperationException if the OS doesn't support process creation.
* @throws IOException if an I/O error occurs.
* @throws ProcessTimedOutException if the timeout expires before the process finishes.
* @throws ProcessFailedException if the process returns a non-zero exit status.
*/
fun runProcess(vararg command: String, workingDir: File? = null, timeoutSecs: Long = 300,
                throwOnFailure: Boolean = true): ProcessResult {
    val proc = ProcessBuilder(*command)
                .directory(workingDir)
                .start()

    // Must read both output and error, else it can deadlock.

    class StreamReader(val stream: InputStream, val result: StringBuilder) : Runnable {
        override fun run() = stream.bufferedReader().use { s ->
            while (true)
                result.appendln(s.readLine() ?: break)
        }
    }

    val output = StringBuilder()
    Thread(StreamReader(proc.inputStream, output)).start()
    val error = StringBuilder()
    Thread(StreamReader(proc.errorStream, error)).start()

    val exited = proc.waitFor(timeoutSecs, TimeUnit.SECONDS)

    if (!exited)
        throw ProcessTimedOutException("${command[0]} timed out!", timeoutSecs, output.toString(), error.toString())
    val exitValue = proc.exitValue()
    if (exitValue != 0 && throwOnFailure)
        throw ProcessFailedException("${command[0]} failed: $error", exitValue, output.toString(), error.toString())
    return ProcessResult(exitValue, output.toString(), error.toString())
}

/** Thrown if a process doesn't finish within the timeout period. */
class ProcessTimedOutException(msg: String, val timeoutSecs: Long, val output: String, val error: String) : Exception(msg)

/** Thrown if a process returns a non-zero code. */
class ProcessFailedException(msg: String, val exitValue: Int, val output: String, val error: String) : Exception(msg)

/** Returned if a process completes. */
class ProcessResult(val exitValue: Int, val output: String, val error: String)