运行带有超时的命令

发布于 2025-01-12 05:02:08 字数 616 浏览 2 评论 0原文

我正在将命令行程序从 Python 翻译为 Rust。

该程序必须运行无法终止的不同命令。

Python 版本使用 subprocess.run() 接受 timeout 作为参数。

例如:

result = subprocess.run(["java", "MyProgram"],
                        timeout=timeout,
                        capture_output=True)

当翻译成 Rust 时,我使用:

let out = Command::new("java")
    .arg("MyProgram")
    .output()?;

但据我所知,Command 不允许我指定任何超时。

由于它将在 GNU/Linux 上运行,我可以简单地用 timeout 包装调用(如 timeout 10 java MyProgram),但我想知道是否有任何不依赖于的解决方案超时。

所以问题是:如何在 Rust 中运行超时命令?

I'm translating a command line program from Python to Rust.

The program has to run different commands that could not terminate.

The Python version uses subprocess.run() that accepts timeout as argument.

For example:

result = subprocess.run(["java", "MyProgram"],
                        timeout=timeout,
                        capture_output=True)

When translating into Rust, I'm using:

let out = Command::new("java")
    .arg("MyProgram")
    .output()?;

But as long as I know, Command is not allowing me to specify any timeout.

Since it will run on GNU/Linux, I could simply wrap the call with timeout (as in timeout 10 java MyProgram) but I wonder if there's any solution that does not depend on timeout.

So the question is: how do I run a command from Rust with a timeout?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

断舍离 2025-01-19 05:02:08

有几种方法可以解决这个问题。

一种方法是启动后台线程并使用 Child::kill() 在超时后终止进程。您需要使用 Arc 在线程之间共享对象。但这有点问题,因为 Child 的方法需要对 Child 的可变引用,因此您不能同时从一个线程等待该进程你试图从另一个人那里杀死它。

另一种方法是在自旋循环中使用Child::try_wait(),并在挂钟超过阈值时间时终止进程。

或者,考虑使用 wait_timeout 包,它将这种复杂性包装在一个简单的函数后面。

There's a few ways you could handle this.

One would be to start a background thread and use Child::kill() to kill the process after a timeout. You would need to use Arc to share the object between threads. This is a bit problematic though because the methods of Child require a mutable reference to the Child, so you can't wait on the process from one thread at the same time as you try to kill it from another.

Another approach would be to use Child::try_wait() in a spinloop and kill the process when the wall clock has passed a threshold time.

Alternatively, consider using the wait_timeout crate, which wraps up this complexity behind a simple function.

南…巷孤猫 2025-01-19 05:02:08

简短回答:

如果像我一样,由于使用 SIG_CHLD 而无法使用 wait_timeout 箱,那么您可能有兴趣使用 child_wait_timeout,没有这个限制(我是这个箱子的作者)。

长答案:

我知道这个问题已经很老了,我只想对已接受的答案发表评论,但我对此没有足够的声誉。

我在搜索如何在 Rust 中执行 wait_timeout 时偶然发现了这个问题。在我的情况下,wait_timeout 箱由于使用 SIG_CHLD 而无法使用。经过一番研究,我发现了另外两种在 Rust 中实现异步 wait_timeout 的方法:

  1. 针对 Linux 内核 5.3 及更高版本,基于 pidfd_open
  2. 另一种 100% POSIX 兼容的方法,基于 pthread_cancel

这些实现可在 child_wait_timeout 箱 (https://docs.rs /child_wait_timeout/latest/child_wait_timeout/)。

所有这些方法都是异步的,并且与使用信号的方法类似,开销可以忽略不计(板条箱中提供了基准)。

Short answer:

If, like me, you cannot use the wait_timeout crate due to its use of SIG_CHLD, you might be interested in using child_wait_timeout, which doesn't have this limitation (I am the author of this crate).

Long answer:

I know this question is quite old, and I only wanted to comment on the accepted answer, but I do not have enough reputation for it.

I stumbled upon this question while searching for how to perform a wait_timeout in Rust. In my situation, the wait_timeout crate is not usable due to its use of SIG_CHLD. After some research, I found two other ways to implement an async wait_timeout in Rust:

  1. For Linux kernel 5.3 and later, based on pidfd_open.
  2. Another 100% POSIX-compliant method, based on pthread_cancel.

These implementations are available in the child_wait_timeout crate (https://docs.rs/child_wait_timeout/latest/child_wait_timeout/).

All these methods are asynchronous and have negligible overhead similarly to the method that use signal (benchmark available in the crate).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文