linux - 在某些特定情况下没有从 ProcessBuilder 的输入流中得到响应
问题描述
所以我试图从linux获取电池状态,到目前为止第一个命令(路径变量)完美返回,我能够从输入流中以序列的形式获得它的响应,但不幸的是第二个命令(结果变量)返回空序列。
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
取自这里
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
}
解决方案
这里的问题是管道。
你正在尝试运行一个管道——一个涉及运行多个程序的结构,需要一个 shell 来解释。
但是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 实例,然后它可以运行你的管道;看到这个答案。
但是在您自己的代码中进行过滤并完全避免调用可能会更简单、更安全、更有效grep
。
我建议捕获进程的错误输出,这很可能会使问题变得清晰。
推荐阅读
- java - 使用 Accounts.UUID 和 UUID = 时的 MySQL 语法问题,有两个表
- python - 在熊猫中水平执行 pd.concat 并在列上匹配的最佳方法是什么?
- angular - Jasmine-Karma UnitTest 运行单一与运行所有
- java - 线程“主”java.lang.NoClassDefFoundError 中的异常:org/joda/time/DateTime Spark
- sql - Laravel/SQL:列等于 NOT 和 NULL
- javascript - Javascript:将http请求正文读取为字节数组
- php - 在 *.tpl 文件中获取购物车内容
- c# - 无法从 C# 控制台应用程序中的 SOAP 1.2 Web 请求获得响应
- r - 加速包含 coxph 函数调用的 for 循环
- reactjs - 无法根据第一个数组的值显示第二个数组的数据