#unix #rust #subprocess
Вопрос:
У меня есть процесс Rust, который должен запустить подпроцесс, а затем немедленно выйти. Похоже, это работает:
fn main() {
// Intentionally drop the returned Child and exit
Command::new("bash").args(amp;["-c", "sleep 10s; touch done"]).spawn().unwrap();
}
Запуск этого процесса немедленно завершается, и bash
процесс продолжается:
$ cargo build; target/debug/demo
$ ps aux | grep bash
dimo414 35959 0.0 0.0 4278616 1484 s001 S 1:12PM 0:00.00 bash -c sleep 10s; touch done
...
Однако, если я добавлю еще один слой и попытаюсь вызвать свой двоичный файл и дождаться его завершения, это также приведет к ожиданию подпроцесса, в отличие от того, что я наблюдаю в оболочке. Вот МАКВЕ:
fn main() {
let exec = std::env::current_exe().expect("Could not resolve executable location");
// First re-invoke the same binary and await it
if std::env::args().len() < 2 {
println!("Ran Subprocess:n{:?}", Command::new(exec).arg("").output().unwrap());
} else {
// In that subprocess spawn a long-running process but don't wait
println!("Spawning Subprocess");
Command::new("bash").args(amp;["-c", "sleep 10s; touch done"]).spawn().unwrap();
}
}
$ cargo build; target/debug/demo
# doesn't terminate until the bash process does
Есть ли способ завершить процесс верхнего уровня, не дожидаясь вложенного процесса?
Ответ №1:
Пожалуйста, проверьте ссылку на spawn
Выполняет команду как дочерний процесс, возвращая ей дескриптор.
По умолчанию стандартный ввод данных, стандартный вывод и стандартный вывод данных наследуются от родителя.
Когда вы запускаете себя как подпроцесс, он порождает другой подпроцесс с наследованием stdio от родителя. Поскольку ваш процесс верхнего уровня использует output()
его, он будет ждать завершения подпроцесса и собирать все его выходные данные (ссылки).
Давайте продемонстрируем это так:
Корень -> Sub1 ->> >>Sub2
Sub2 использует канал stdout Sub1, Root ожидает сбора всех выходных данных от Sub1, которые все еще используются Sub2, в конце дня Root ожидает завершения Sub2.
Решение таково: просто используйте Stdio::null()
для отправки выходных данных /dev/null
, так как ваш корневой процесс не заботится о выводе Sub2.
fn main() {
let exec = std::env::current_exe().expect("Could not resolve executable location");
if std::env::args().len() < 2 {
println!(
"Ran Subprocess:n{:?}",
Command::new(exec).arg("").output().unwrap()
);
} else {
println!("Spawning Subprocess");
Command::new("bash")
.stdout(Stdio::null())
.stderr(Stdio::null())
.args(amp;["-c", "sleep 10s; touch done"])
.spawn()
.unwrap();
}
}
Комментарии:
1. Потрясающее спасибо, я должен был это понять 🙂