После дальнейшего обсуждения мы определили фактическую проблему: запускаемая вами программа должна оставаться на переднем плане, чтобы она могла читать с терминала (что фоновые процессы не могут делать в Unix).
Есть два способа добиться этого.Первое и самое простое - дождаться дочернего процесса до выхода из родительского процесса:
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()
}
Это гарантирует, что процессы (родительский и дочерний) остаются на переднем плане, поскольку оболочка ожидает родительского процесса.процесс, так что дочерний процесс может читать из терминала.
Если по какой-то причине вы не можете позволить родительскому процессу задерживаться во время выполнения дочернего процесса, вам необходим код, зависящий от платформы.В Unix вы можете использовать некоторые системные вызовы из exec()
familiy, чтобы заменить изображение родительского процесса на изображение дочернего процесса:
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()
}
Функция возвращается только в случае ошибки.В противном случае образ процесса заменяется новым.С точки зрения оболочки, это все тот же процесс, поэтому оболочка будет ожидать завершения команды, которую вы запустили.
Преимущества второго подхода кажутся незначительными.Он не работает в Windows, поскольку Windows не поддерживает exec()
и друзей.Во время выполнения команды у вас будет на один процесс меньше, но на практике использование этого процесса должно быть небольшим - он не использует ЦП, и страницы памяти можно при необходимости заменить.
ОригиналОтвет
Из программы A, написанной на ржавчине, я хочу запустить программу B, завершить ее A и, как правило, запустить B так же, как если бы он был запущен вручную из той же оболочки сразу после завершенияA.
Это более или менее то, что ваш код уже делает.Однако у процесса, запускаемого непосредственно из оболочки в системах Unix, есть несколько отличий:
- Новый процесс не будет включен в список заданий оболочки, поэтому вы не можете использовать задание оболочкиуправляющие команды, такие как
bg
и fg
. - Новый процесс будет выполняться в фоновом режиме, и оболочка сразу же покажет приглашение после выхода из программ Rust.
Это происходит сбой, потому что nvim запускается как дочерний и уничтожается, как только вызывающая программа останавливается.
Это не так, ни для Unix ни для Windows .
Как мне написать выполнить , чтобы программа вызывающего абонента немедленно остановилась и позволила nvim (или другую программу) правильно работать (даже без оконной системы)?
Это должно быть именно то, что делает ваш код Rust (и то, что он делает при запуске на моей машине с Linux).Код в вашем ответе, с другой стороны, делает что-то еще: он использует execv()
до , заменяет процесс Rust на nvim.По сути, процесс не немедленно останавливается, а остаток оболочки блокируется до выхода nvim.