使用 java Runtime.exec() 执行 yum 安装程序并捕获其下载进度
我面临着过去几个月的问题。我已经努力寻找解决方案。
我在 Fedora 14 上使用 Java
问题是,我尝试使用 Runtime.exec("yum -y install somePkg") 下载并安装包,但是当我使用 pc.getInputStream() 捕获标准输出时,我不这样做无法查看当前的下载进度状态,即任何形式的下载百分比。输出一直显示“正在下载软件包:”,直到 yum 完成下载。下载成功后。我在输出控制台中仅看到总体已安装的软件包列表和下载完整消息。
我需要一个解决方案,即使它很脏。我需要以某种方式使用 java 捕获 yum 的整个下载进度。
I'm facing a problem from past few months. I have tried hard to find a solution.
I'm using Java over Fedora 14
The problem is, I'm trying to download and install a package using Runtime.exec("yum -y install somePkg") but when I use pc.getInputStream() to capture stdout, I don't get to see the current download progress status i.e. the percentage download in any form. The output sticks at 'downloading packages:' until yum has finished downloading. After successful download. I see only a overall installed packages list and donwload complete message in the output console.
I need a solution even if it's a dirty one. I need to somehow capture the whole download progress of yum using java.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
按照要求直接回答问题:
在 Yum (/usr/share/yum-cli/output.py) 源中找到:
因此,hacky 解决方案是为 Yum 分配一个 pty .. 不幸的是,
看起来现有的 Java 库不提供对 Linux 用于分配 PTY 的 ptmx 接口的访问(尽管可以想象,可以通过 JNI 绑定来实现这一点 - 代码不会非常复杂;尽管快速的谷歌搜索没有找到任何好的库存库来这样做,所以也许我遗漏了一些东西,或者我怀疑有人现在应该有一个),所以“最简单”的方法可能是编写一个 Python 包装器,调用 Yum 内部执行其命令,并请求回调。无论哪种方式,不是纯 Java,而是链接到外部 Python 解释器(并且,由于 Yum 是 Python,您知道必须安装一个解释器)可能比使用某些 C 代码进行 JNI 链接要少一些麻烦。 (例如,您可以查看 /usr/share/PackageKit/helpers/yum/yumBackend.py 中的 ProcessTransPackageKitCallback)
但是:
或者,您是否考虑过使用 pkcon 或使用 DBus 来与 PackageKit 交谈?
使用 DBus 不需要外部库,但可能需要重新考虑您的安装过程。 http://dbus.freedesktop.org/doc/dbus-java/ 有一个 Java DBus 库包装连接逻辑,此时 http://www.packagekit.org/pk-faq.html#session-methods 应该给你访问它的要点。我相信 DBus 接口提供了一种在事务处理过程中检查事务的方法 - 但我对 DBus 还不够熟悉,无法对此效果给出可靠的声明。这可能是我看到的最不“hacky”的解决方案;而且,作为奖励,它至少可以移植到 Ubuntu(我相信)。
然而,pkcon 将是一个选择。它似乎以一种很好的、可解析的格式将进度写入标准输出,尽管它在不是 tty 时确实减少了输出:
这是实际的输出,因此粒度不是那么好,但它看起来对于解析非常友好。
恐怕我没有 Fedora 14 盒子可供比较——这是 Fedora 15 上的——所以你的情况可能会有所不同。
Directly answering the question, as asked:
Found in the Yum (/usr/share/yum-cli/output.py) source:
So, the hacky solution would be to allocate a pty for Yum...
Unfortunately, it looks like the stock Java libraries don't provide access to the ptmx interface that Linux uses for allocating PTY's (although, one could conceivably do so with a JNI binding — the code would not be terribly complex; although a quick Google search didn't turn up any nice stock libraries to do so, so perhaps there's something I'm missing, or I would suspect someone should have one lying around by now), so the “easiest” way to do this might be to write a Python wrapper that calls into the Yum internals to do its bidding, and asks for a callback. Either way, not pure Java, but linking to an external Python interpreter (and, since Yum is Python, you know that there must be one installed) might be less hassle than doing JNI linking with some C code. (As an example, you might peek at ProcessTransPackageKitCallback in /usr/share/PackageKit/helpers/yum/yumBackend.py)
However:
Alternatively, have you considered using pkcon, or using DBus to talk to PackageKit?
Using DBus wouldn't require external libraries, but might require rethinking your installation process a bit. There's a Java DBus library at http://dbus.freedesktop.org/doc/dbus-java/ that wraps the connection logic, at which point, the examples at http://www.packagekit.org/pk-faq.html#session-methods should give you the gist of accessing it. I believe that the DBus interface provides a way to check on a transaction as it progresses — but I'm not familiar enough with DBus to give a solid statement to that effect. That might be the least "hacky" solution I see; and, as a bonus, it's portable to Ubuntu, at least (I believe).
pkcon, however, would be an option. It appears to write progress to stdout in a nice, parseable format, even though it does reduce its output when it's not a tty:
That's the actual output, so the granularity isn't so great, but it looks pretty friendly for parsing.
I'm afraid I don't have a Fedora 14 box to compare against — this is on Fedora 15 — so your mileage may vary.
创建一个新的 ProcessBuilder 实例。调用 start() 方法后,尝试使用 getInputStream() 和/或 getErrorStream() 处理 Process IO。
另一个提示可能是在调用 start 方法之后但在获取 InputStream 之前,调用 Thread.sleep(a while)。
create a new ProcessBuilder instance. After called start() method, try to handle Process IO with getInputStream() and/or getErrorStream().
Another tips could be after call start method but before get the InputStream, call Thread.sleep(a while).