启动另一个程序然后退出 [英] Start another program then quit

查看:71
本文介绍了启动另一个程序然后退出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从一个用 rust 编写的程序 A,我想启动一个程序 B,让 A 结束,让 B 正常运行,就像在 A 终止后从同一个 shell 手动启动一样.

From a program A written in rust, I want to start a program B, have A end, and have B normally run just like if it was manually launched from the same shell just after termination of A.

我目前的程序:

use std::process::Command;

pub fn execute(exe: &str, args: &[&str]) {
    Command::new(exe)
        .args(args)
        .spawn()
        .expect("failed to start external executable");
}

fn main() {
    execute("/usr/bin/nvim", &["/home/dys/todo.txt"]);
}

这失败了.nvim 是作为一个孩子启动的,一旦调用程序停止,它就无法工作.

This fails. nvim is launched as a child and is non-working as soon as the calling program stops.

如何编写 execute 以便调用程序立即停止并让 nvim(或其他程序)正常运行(即使没有任何窗口系统)?

How can I write execute so the caller program immediately stops and lets nvim (or another program) properly run (even without any windowing system) ?

推荐答案

经过进一步讨论,我们确定了实际问题:您正在启动的程序应该留在前台,因此它可以从终端读取(哪个后台进程不能在 Unix 上执行).

After further discussion, we identified the actual problem: The program you are launching is supposed to stay in the foreground, so it can read from the terminal (which background processes can't do on Unix).

有两种方法可以实现这一点.第一个也是最简单的方法是在父进程退出之前等待子进程:

There are two ways to achieve this. The first, and easiest, is to wait for the child process before the parent process exits:

use std::process::{Command, ExitStatus};
use std::io::Result;

pub fn execute(exe: &str, args: &[&str]) -> Result<ExitStatus> {
    Command::new(exe).args(args).spawn()?.wait()
}

这确保进程(父进程和子进程)保持在前台,因为 shell 正在等待父进程,所以子进程可以从终端读取.

This ensures the processes (parent and child) stay in the foreground, since the shell is waiting for the parent process, so the child process can read from the terminal.

如果由于某种原因您无法承受父进程在子进程运行时逗留,那么您需要依赖于平台的代码.在 Unix 上,您可以使用 exec() 家族中的一些系统调用来将父进程的映像替换为子进程的映像:

If for some reason you can't afford the parent process to linger on while the child process is running, you need platform-dependent code. On Unix, you can use some syscall from the exec() familiy to replace the image of the parent process with the image of the child process:

use std::process::Command;
use std::os::unix::process::CommandExt;
use std::io::Error;

pub fn execute(exe: &str, args: &[&str]) -> Error {
    Command::new(exe).args(args).exec()
}

该函数仅在出现错误时返回.否则,过程映像将被新映像替换.从 shell 的角度来看,它仍然是相同的过程,因此 shell 将等待您启动的命令完成.

The function only returns if there is an error. Otherwise, the process image is replaced by the new image. From the viewpoint of the shell, it's still the same process, so the shell will wait for the command you launched to finish.

第二种方法的优势似乎微乎其微.它不适用于 Windows,因为 Windows 不支持 exec() 和朋友.运行该命令时,您将少一个进程,但该进程的资源使用量在实践中应该很小——它不使用任何 CPU,必要时可以换出内存页.

The advantages of the second approach seem slim. It does not work on Windows, since Windows does not support exec() and friends. You will have one less process around while running the command, but the resource usage of that process should be small in practice – it does not use any CPU, and the memory pages can be swapped out if necessary.

从一个用 rust 编写的程序 A,我想启动一个程序 B,让 A 结束,让 B 正常运行,就像在 A 终止后从同一个 shell 手动启动一样.

From a program A written in rust, I want to start a program B, have A end, and have B normally run just like if it was manually launched from the same shell just after termination of A.

这或多或少是您的代码已经在做的事情.不过,在 Unix 系统上直接从 shell 启动的进程有一些不同:

This is more or less what your code is already doing. There are a few differences to a process launched directly from the shell on Unix systems, though:

  • 新进程将不会包含在 shell 的作业列表中,因此您不能使用 shell 的作业控制命令,例如 bgfg.
  • 新进程将在后台运行,Rust 程序退出后,shell 将立即显示提示.

这会失败,因为 nvim 是作为孩子启动的,并且在调用程序停止后立即被终止.

This fails because nvim is launched as a child and is killed as soon as the calling program stops.

这不是真的,对于 UnixWindows.

This is not true, neither for Unix nor for Windows.

如何编写 execute 以便调用程序立即停止并让 nvim(或其他程序)正常运行(即使没有任何窗口系统)?

How can I write execute so the caller program immediately stops and lets nvim (or another program) properly run (even without any windowing system)?

这应该正是您的 Rust 代码正在执行的操作(以及它在我的 Linux 机器上运行时的操作).另一方面,您的答案中的代码做了其他事情:它使用 execv() 用 nvim 替换 Rust 进程.实际上,该进程不会立即停止,并且 shell 一直处于阻塞状态,直到 nvim 退出.

This should be exactly what your Rust code is doing (and what it does when run on my Linux machine). The code in your answer, on the other hand, does something else: It uses execv() to replace the Rust process with nvim. In effect, the process does not immediately stop, and the shell remaind blocked until nvim exits.

这篇关于启动另一个程序然后退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆