Структура Command
pub struct Command { /* private fields */ }
process.Эта структура имитирует API std::process::Command из стандартной библиотеки, но заменяет функции, создающие процесс, асинхронным вариантом. Основные предоставляемые асинхронные функции: spawn, status и output.
Command использует асинхронные версии некоторых типов std (например, Child).
Реализации
impl Command
pub fn new<S: AsRef<OsStr>>(program: S) -> Command
Создаёт новый Command для запуска программы по пути program со следующими настройками по умолчанию:
- Программе не передаются аргументы
- Наследуется окружение текущего процесса
- Наследуется рабочий каталог текущего процесса
- Для
spawnилиstatusнаследуются stdin/stdout/stderr, а дляoutputсоздаются каналы
Методы-сборщики позволяют изменить эти настройки по умолчанию и настроить процесс.
Если program не является абсолютным путём, поиск PATH будет выполняться способом, определяемым операционной системой.
Путь поиска можно задать, установив переменную окружения PATH для Command, однако в Windows это ограничено особенностями реализации (см. issue rust-lang/rust#37519).
Примеры
Пример использования:
use tokio::process::Command;
let mut command = Command::new("sh");pub fn as_std(&self) -> &StdCommand
Преобразует с минимальными затратами в &std::process::Command для случаев, когда ожидается тип из стандартной библиотеки.
pub fn as_std_mut(&mut self) -> &mut StdCommand
Преобразует с минимальными затратами в &mut std::process::Command для случаев, когда ожидается тип из стандартной библиотеки.
pub fn into_std(self) -> StdCommand
Преобразует с минимальными затратами в std::process::Command.
Обратите внимание, что специфичные для Tokio параметры будут потеряны. В настоящее время это относится только к kill_on_drop.
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command
Добавляет аргумент, передаваемый программе.
За один вызов можно передать только один аргумент. Поэтому вместо:
let mut command = tokio::process::Command::new("sh");
command.arg("-C /path/to/repo");
следует использовать:
let mut command = tokio::process::Command::new("sh");
command.arg("-C");
command.arg("/path/to/repo");
Чтобы передать несколько аргументов, см. args.
Примеры
Пример использования:
use tokio::process::Command;
let output = Command::new("ls")
.arg("-l")
.arg("-a")
.output().await.unwrap();
pub fn args<I, S>(&mut self, args: I) -> &mut Command
Добавляет несколько аргументов, передаваемых программе.
Чтобы передать один аргумент, см. arg.
Примеры
Пример использования:
use tokio::process::Command;
let output = Command::new("ls")
.args(&["-l", "-a"])
.output().await.unwrap();pub fn raw_arg<S: AsRef<OsStr>>( &mut self, text_to_append_as_is: S, ) -> &mut Command
Добавляет буквальный текст в командную строку без экранирования и заключения в кавычки.
Это полезно для передачи аргументов в cmd.exe /c, где правила экранирования отличаются от CommandLineToArgvW.
pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
Добавляет или обновляет соответствие переменной окружения.
Обратите внимание: имена переменных окружения не учитывают регистр (но сохраняют его) в Windows и учитывают регистр на всех остальных платформах.
Примеры
Пример использования:
use tokio::process::Command;
let output = Command::new("ls")
.env("PATH", "/bin")
.output().await.unwrap();pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Command
Добавляет или обновляет несколько соответствий переменных окружения.
Примеры
Пример использования:
use tokio::process::Command;
use std::process::{Stdio};
use std::env;
use std::collections::HashMap;
let filtered_env : HashMap<String, String> =
env::vars().filter(|&(ref k, _)|
k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH"
).collect();
let output = Command::new("printenv")
.stdin(Stdio::null())
.stdout(Stdio::inherit())
.env_clear()
.envs(&filtered_env)
.output().await.unwrap();pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command
Удаляет соответствие переменной окружения.
Примеры
Пример использования:
use tokio::process::Command;
let output = Command::new("ls")
.env_remove("PATH")
.output().await.unwrap();pub fn env_clear(&mut self) -> &mut Command
Очищает всю карту окружения дочернего процесса.
Примеры
Пример использования:
use tokio::process::Command;
let output = Command::new("ls")
.env_clear()
.output().await.unwrap();pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command
Задает рабочий каталог для дочернего процесса.
Поведение, зависящее от платформы
Если путь к программе относительный (например, "./script.sh"), неоднозначно, следует ли интерпретировать его относительно рабочего каталога родительского процесса или относительно current_dir. В этом случае поведение зависит от платформы и не гарантируется; рекомендуется использовать canonicalize, чтобы получить абсолютный путь к программе.
Примеры
Пример использования:
use tokio::process::Command;
let output = Command::new("ls")
.current_dir("/bin")
.output().await.unwrap();pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command
Задает конфигурацию стандартного потока ввода (stdin) дочернего процесса.
По умолчанию используется inherit.
Примеры
Пример использования:
use std::process::{Stdio};
use tokio::process::Command;
let output = Command::new("ls")
.stdin(Stdio::null())
.output().await.unwrap();pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command
Задает конфигурацию стандартного потока вывода (stdout) дочернего процесса.
По умолчанию используется inherit при использовании с spawn или status, а при использовании с output по умолчанию используется piped.
Примеры
Пример использования:
use tokio::process::Command;
use std::process::Stdio;
let output = Command::new("ls")
.stdout(Stdio::null())
.output().await.unwrap();pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Command
Задаёт конфигурацию стандартного потока ошибок (stderr) дочернего процесса.
По умолчанию используется inherit при использовании с spawn или status, а при использовании с output по умолчанию применяется piped.
Примеры
Базовый пример:
use tokio::process::Command;
use std::process::{Stdio};
let output = Command::new("ls")
.stderr(Stdio::null())
.output().await.unwrap();pub fn kill_on_drop(&mut self, kill_on_drop: bool) -> &mut Command
Определяет, следует ли вызывать операцию kill для запущенного дочернего процесса при удалении соответствующего дескриптора Child.
По умолчанию предполагается значение false: следующий запущенный процесс не будет завершён при удалении дескриптора, что соответствует поведению стандартной библиотеки.
Предостережения
На платформах Unix родительский процесс должен «собирать» завершившиеся дочерние процессы, чтобы освободить все ресурсы ОС. Завершившийся дочерний процесс, который ещё не был собран родительским, считается процессом-зомби. Такие процессы продолжают учитываться при ограничениях, установленных системой, а слишком большое количество процессов-зомби может помешать запуску новых процессов.
Хотя отправка сигнала kill дочернему процессу является синхронной операцией, образовавшийся процесс-зомби нельзя .await в деструкторе, чтобы не блокировать другие задачи. Среда выполнения tokio в фоновом режиме постарается собрать и очистить такие процессы, однако никаких дополнительных гарантий относительно скорости или частоты выполнения этой процедуры не предоставляется.
Если требуются более строгие гарантии, рекомендуется по возможности не удалять дескриптор Child, а вместо этого использовать child.wait().await или child.kill().await.
pub fn creation_flags(&mut self, flags: u32) -> &mut Command
Задаёт флаги создания процесса, передаваемые в CreateProcess.
Они всегда будут объединяться с помощью OR с CREATE_UNICODE_ENVIRONMENT.
pub fn uid(&mut self, id: u32) -> &mut Command
Задаёт идентификатор пользователя дочернего процесса. Это приводит к вызову setuid в дочернем процессе. Ошибка при вызове setuid приведёт к сбою запуска.
pub unsafe fn pre_exec<F>(&mut self, f: F) -> &mut Command
Планирует выполнение замыкания непосредственно перед вызовом функции exec.
Замыкание может вернуть ошибку ввода-вывода; её код ошибки ОС будет передан родительскому процессу и возвращён как ошибка при запросе на запуск процесса.
Можно зарегистрировать несколько замыканий; они будут вызваны в порядке регистрации. Если замыкание возвращает Err, последующие замыкания вызваны не будут, а операция запуска немедленно завершится с ошибкой.
Безопасность
Это замыкание будет выполнено в контексте дочернего процесса после fork. Прежде всего это означает, что любые изменения памяти, выполненные этим замыканием, не будут видны родительскому процессу. Часто среда выполнения сильно ограничена: обычные операции, такие как malloc или получение мьютекса, могут не работать (например, из-за других потоков, которые всё ещё выполняются после запуска fork).
Это также означает, что все ресурсы, такие как файловые дескрипторы и области памяти, отображённые в память, были дублированы. Вы несёте ответственность за то, чтобы замыкание не нарушало инварианты библиотеки из-за некорректного использования этих дубликатов.
К моменту вызова этого замыкания такие параметры, как файловые дескрипторы стандартных потоков ввода-вывода и рабочий каталог, уже изменены, поэтому вывод в эти места может появиться не там, где ожидалось.
pub fn process_group(&mut self, pgroup: i32) -> &mut Command
Устанавливает идентификатор группы процессов (PGID) дочернего процесса. Эквивалентно вызову setpgid в дочернем процессе, но может быть эффективнее.
Группы процессов определяют, какие процессы получают сигналы.
Примеры
Нажатие Ctrl-C в терминале отправляет SIGINT всем процессам в текущей группе процессов переднего плана. Если запустить подпроцесс sleep в новой группе процессов, он не получит от терминала сигнал SIGINT.
Родительский процесс может установить обработчик сигнала и управлять процессом по своему усмотрению.
Если идентификатор группы процессов равен 0, в качестве PGID будет использоваться идентификатор процесса.
use tokio::process::Command;
let output = Command::new("sleep")
.arg("10")
.process_group(0)
.output()
.await
.unwrap();pub fn spawn(&mut self) -> Result<Child>
Запускает команду как дочерний процесс и возвращает дескриптор для работы с ним.
По умолчанию дочерний процесс наследует stdin, stdout и stderr родительского процесса.
Этот метод синхронно запускает дочерний процесс и возвращает дескриптор дочернего процесса, поддерживающий работу с future. Возвращённый Child реализует Future для получения ExitStatus дочернего процесса; кроме того, у Child есть методы для получения дескрипторов потоков stdin, stdout и stderr.
Весь ввод-вывод этого дочернего процесса будет связан с текущим циклом событий по умолчанию.
Примеры
Пример базового использования:
use tokio::process::Command;
async fn run_ls() -> std::process::ExitStatus {
Command::new("ls")
.spawn()
.expect("ls command failed to start")
.wait()
.await
.expect("ls command failed to run")
}Предостережения
Удаление/отмена
Как и в стандартной библиотеке, в отличие от парадигмы futures, где удаление подразумевает отмену, запущенный процесс по умолчанию продолжит работу даже после удаления дескриптора Child.
Метод Command::kill_on_drop позволяет изменить это поведение и завершить дочерний процесс, если оболочка Child удалена до завершения процесса.
Процессы Unix
На платформах Unix родительский процесс должен «собирать» завершившиеся дочерние процессы, чтобы освободить все ресурсы ОС. Завершившийся дочерний процесс, который родитель ещё не собрал, считается процессом-зомби. Такие процессы продолжают учитываться в системных ограничениях, а слишком большое количество процессов-зомби может помешать запуску новых процессов.
Среда выполнения tokio по возможности старается собирать и очищать все запущенные ею процессы. Никаких дополнительных гарантий относительно скорости или частоты выполнения этой процедуры не предоставляется.
Если требуются более строгие гарантии очистки, рекомендуется не удалять дескриптор процесса Child, пока для него не будет выполнено await.
Ошибки
На платформах Unix этот метод завершится ошибкой std::io::ErrorKind::WouldBlock, если будет достигнут системный лимит процессов (с учётом других приложений, работающих в системе).
pub fn spawn_with( &mut self, with: impl FnOnce(&mut StdCommand) -> Result<StdChild>, ) -> Result<Child>
tokio_unstable.Запускает команду как дочерний процесс с пользовательской функцией запуска и возвращает дескриптор этого процесса.
Во всех аспектах этот метод идентичен Self::spawn, за исключением запуска: здесь его можно настроить с помощью параметра with, вместо того чтобы использовать обычный запуск по умолчанию. Фактически, Self::spawn — это просто Self::spawn_with с StdCommand::spawn.
Пока что этот метод в основном полезен в Windows, поскольку платформа предоставляет специальные API для настройки дочерних процессов при запуске с различными атрибутами, позволяющими точно изменить поведение операции запуска.
Примеры
Базовый пример:
use std::process::Stdio;
let output = tokio::process::Command::new("ls")
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn_with(std::process::Command::spawn)
.unwrap()
.wait_with_output()
.await
.unwrap();Настройка запуска в Windows:
#![feature(windows_process_extensions_raw_attribute)]
use std::os::windows::process::{CommandExt, ProcThreadAttributeList};
use std::process::Stdio;
use tokio::process::Command;
let parent = Command::new("cmd").spawn().unwrap();
let parent_process_handle = parent.raw_handle();
const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: usize = 0x00020000;
let attribute_list = ProcThreadAttributeList::build()
.attribute(PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &parent_process_handle)
.finish()
.unwrap();
let _output = Command::new("ls")
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn_with(|cmd| cmd.spawn_with_attributes(&attribute_list))
.unwrap()
.wait_with_output()
.await
.unwrap();
pub fn status(&mut self) -> impl Future<Output = Result<ExitStatus>>
Запускает команду как дочерний процесс, ожидает его завершения и получает его код завершения.
По умолчанию stdin, stdout и stderr наследуются от родительского процесса. Если для какого-либо дескриптора ввода/вывода настроен канал, он будет немедленно закрыт после запуска дочернего процесса.
Весь ввод-вывод этого дочернего процесса будет связан с текущим циклом обработки событий по умолчанию.
Деструктор future, возвращённого этой функцией, завершит дочерний процесс, если для kill_on_drop установлено значение true.
Ошибки
Этот future вернёт ошибку, если не удастся запустить дочерний процесс или если произойдёт ошибка при ожидании его завершения.
На платформах Unix этот метод вернёт ошибку std::io::ErrorKind::WouldBlock, если будет достигнут системный лимит процессов (включая процессы других приложений, запущенных в системе).
Примеры
Базовый пример:
use tokio::process::Command;
async fn run_ls() -> std::process::ExitStatus {
Command::new("ls")
.status()
.await
.expect("ls command failed to run")
}pub fn output(&mut self) -> impl Future<Output = Result<Output>>
Запускает команду как дочерний процесс, ожидает его завершения и собирает весь его вывод.
Примечание: в отличие от стандартной библиотеки, этот метод безусловно настраивает дескрипторы stdout/stderr как каналы, даже если они были настроены ранее. Если это нежелательно, следует использовать метод
spawnв сочетании с методомwait_with_outputдля дочернего процесса.
Этот метод вернёт future, представляющий сбор stdout/stderr дочернего процесса. Он разрешится в тип Output из стандартной библиотеки, содержащий stdout и stderr в качестве Vec<u8>, а также ExitStatus, представляющий способ завершения процесса.
Весь ввод-вывод этого дочернего процесса будет связан с текущим циклом обработки событий по умолчанию.
Деструктор future, возвращённого этой функцией, завершит дочерний процесс, если для kill_on_drop установлено значение true.
Ошибки
Этот future вернёт ошибку, если не удастся запустить дочерний процесс или если произойдёт ошибка при ожидании его завершения.
На платформах Unix этот метод вернёт ошибку std::io::ErrorKind::WouldBlock, если будет достигнут системный лимит процессов (включая процессы других приложений, запущенных в системе).
Примеры
Базовый пример:
use tokio::process::Command;
async fn run_ls() {
let output: std::process::Output = Command::new("ls")
.output()
.await
.expect("ls command failed to run");
println!("stderr of ls: {:?}", output.stderr);
}pub fn get_kill_on_drop(&self) -> bool
Возвращает логическое значение, ранее установленное методом Command::kill_on_drop.
Обратите внимание: если вы ранее не вызывали Command::kill_on_drop, здесь будет возвращено значение false по умолчанию.
Примеры
use tokio::process::Command;
let mut cmd = Command::new("echo");
assert!(!cmd.get_kill_on_drop());
cmd.kill_on_drop(true);
assert!(cmd.get_kill_on_drop());Реализации трейтов
Автоматические реализации трейтов
impl !RefUnwindSafe for Command
impl !UnwindSafe for Command
impl Freeze for Command
impl Send for Command
impl Sync for Command
impl Unpin for Command
impl UnsafeUnpin for Command
Общие реализации
impl<T> BorrowMut<T> for Twhere T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
impl<T> Instrument for T
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
impl<T> WithSubscriber for T
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ
Subscriber к этому типу и возвращает обёртку WithDispatch. Подробнее
MIT License
Copyright © Tokio Contributors
https://docs.rs/tokio/1.53.1/tokio/process/struct.Command.html