在某些特定情况下,没有从ProcessBuilder的输入流中获得响应

问题描述 投票:0回答:1

因此,我试图从linux获取电池状态,到目前为止,第一个命令(路径变量)完美返回,并且我能够从输入流中以Sequence的形式获取其响应,但不幸的是,第二个命令(结果是变量)返回空序列。

fun getLinuxBatteryStatus(): Nothing? {
    val path = """upower --enumerate""".runCommand() ?: return null

    val parameters = listOf("present", "state", "energy-full", "energy", "energy-rate", "time to empty", "percentage")
    val result = """upower -i ${path.first { "battery_BAT" in it }} | grep -E "${parameters.joinToString("|")}""""
        .also { println(it) }
        .runCommand() ?: return null

    result.forEach(::println)   // <- no ouput
    // println(result.count())  // <- 0

    /* Do other thing and return something (that is not related to problem) */
}

输出:

upower -i /org/freedesktop/UPower/devices/battery_BAT1 | grep -E "present|state|energy-full|energy|energy-rate|time to empty|percentage"

上面的输出来自最后一条命令中的also块,仅用于预览命令的字符串以进行调试。如果直接在终端中运行上述命令,我将成功获得如下响应:

    present:             yes
    state:               charging
    energy:              47.903 Wh
    energy-empty:        0 Wh
    energy-full:         50.299 Wh
    energy-full-design:  48.004 Wh
    energy-rate:         17.764 W
    percentage:          95%

为什么最后一个命令在ProcessBuilder中不起作用(不返回任何响应?

注意:扩展功能runCommand取自here

private fun String.runCommand(
    workingDir: File = File("."),
    timeoutAmount: Long = 60,
    timeoutUnit: TimeUnit = TimeUnit.SECONDS
): Sequence<String>? = try {
    ProcessBuilder(split("\\s".toRegex()))
        .directory(workingDir)
        .redirectOutput(ProcessBuilder.Redirect.PIPE)
        .redirectError(ProcessBuilder.Redirect.PIPE)
        .start()
        .apply { waitFor(timeoutAmount, timeoutUnit) }
        .inputStream.bufferedReader().lineSequence()
} catch (e: IOException) {
    e.printStackTrace()
    null
}
linux kotlin processbuilder battery
1个回答
1
投票

这里的问题是管道。

您正在尝试运行管道-一种涉及运行多个程序的构造,需要外壳程序才能解释。

但是ProcessBuilder运行一个程序。在这种情况下,它将运行程序upower,并向其传递参数-i/org/freedesktop/UPower/devices/battery_BAT1|grep-E"present|state|energy-full|energy|energy-rate|time to empty|percentage"。显然,upower不知道如何处理|参数或之后的参数。

您可以使用ProcessBuilder运行shell实例,然后可以运行您的管道;参见this answer

但是在您自己的代码中进行过滤,并且避免完全调用grep,可能会更简单,更安全,更高效。

我建议捕获过程的错误输出,这很可能使问题清楚了。

© www.soinside.com 2019 - 2024. All rights reserved.