Spec-Zone.ru › Tokio

Структура Command

pub struct Command { /* private fields */ }
Доступно только при включённой функции crate 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
where I: IntoIterator<Item = S>, S: AsRef<OsStr>,

Добавляет несколько аргументов, передаваемых программе.

Чтобы передать один аргумент, см. 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

Доступно только в Windows.

Добавляет буквальный текст в командную строку без экранирования и заключения в кавычки.

Это полезно для передачи аргументов в cmd.exe /c, где правила экранирования отличаются от CommandLineToArgvW.

pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
where K: AsRef<OsStr>, V: AsRef<OsStr>,

Добавляет или обновляет соответствие переменной окружения.

Обратите внимание: имена переменных окружения не учитывают регистр (но сохраняют его) в 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
where I: IntoIterator<Item = (K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>,

Добавляет или обновляет несколько соответствий переменных окружения.

Примеры

Пример использования:

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

Доступно только в Windows.

Задаёт флаги создания процесса, передаваемые в CreateProcess.

Они всегда будут объединяться с помощью OR с CREATE_UNICODE_ENVIRONMENT.

pub fn uid(&mut self, id: u32) -> &mut Command

Доступно только в Unix.

Задаёт идентификатор пользователя дочернего процесса. Это приводит к вызову setuid в дочернем процессе. Ошибка при вызове setuid приведёт к сбою запуска.

pub fn gid(&mut self, id: u32) -> &mut Command

Доступно только в Unix.

Аналогично uid, но задаёт идентификатор группы дочернего процесса. Это имеет ту же семантику, что и поле uid.

pub fn arg0<S>(&mut self, arg: S) -> &mut Command
where S: AsRef<OsStr>,

Доступно только в Unix.

Задаёт аргумент исполняемого файла.

Задаёт первый аргумент процесса, argv[0], отличный от пути к исполняемому файлу по умолчанию.

pub unsafe fn pre_exec<F>(&mut self, f: F) -> &mut Command
where F: FnMut() -> Result<()> + Send + Sync + 'static,

Доступно только в Unix.

Планирует выполнение замыкания непосредственно перед вызовом функции exec.

Замыкание может вернуть ошибку ввода-вывода; её код ошибки ОС будет передан родительскому процессу и возвращён как ошибка при запросе на запуск процесса.

Можно зарегистрировать несколько замыканий; они будут вызваны в порядке регистрации. Если замыкание возвращает Err, последующие замыкания вызваны не будут, а операция запуска немедленно завершится с ошибкой.

Безопасность

Это замыкание будет выполнено в контексте дочернего процесса после fork. Прежде всего это означает, что любые изменения памяти, выполненные этим замыканием, не будут видны родительскому процессу. Часто среда выполнения сильно ограничена: обычные операции, такие как malloc или получение мьютекса, могут не работать (например, из-за других потоков, которые всё ещё выполняются после запуска fork).

Это также означает, что все ресурсы, такие как файловые дескрипторы и области памяти, отображённые в память, были дублированы. Вы несёте ответственность за то, чтобы замыкание не нарушало инварианты библиотеки из-за некорректного использования этих дубликатов.

К моменту вызова этого замыкания такие параметры, как файловые дескрипторы стандартных потоков ввода-вывода и рабочий каталог, уже изменены, поэтому вывод в эти места может появиться не там, где ожидалось.

pub fn process_group(&mut self, pgroup: i32) -> &mut Command

Доступно только в Unix.

Устанавливает идентификатор группы процессов (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 Debug for Command

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Форматирует значение с помощью заданного форматтера. Подробнее

impl From<Command> for Command

fn from(std: StdCommand) -> Command

Преобразует входное значение в значение этого типа.

Автоматические реализации трейтов

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> Any for T
where T: 'static + ?Sized,

fn type_id(&self) -> TypeId

Получает TypeId значения self. Подробнее

impl<T> Borrow<T> for T
where T: ?Sized,

fn borrow(&self) -> &T

Неизменяемо заимствует значение из принадлежащего владельцу значения. Подробнее

impl<T> BorrowMut<T> for T
where T: ?Sized,

fn borrow_mut(&mut self) -> &mut T

Изменяемо заимствует значение из принадлежащего владельцу значения. Подробнее

impl<T> From<T> for T

fn from(t: T) -> T

Возвращает аргумент без изменений.

impl<T> Instrument for T

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Инструментирует этот тип с помощью предоставленного Span, возвращая обёртку Instrumented. Подробнее

fn in_current_span(self) -> Instrumented<Self> ⓘ

Инструментирует этот тип с помощью текущего Span, возвращая обёртку Instrumented. Подробнее

impl<T, U> Into<U> for T
where U: From<T>,

fn into(self) -> U

Вызывает U::from(self).

Иными словами, это преобразование выполняет то, что решит реализация From<T> for U.

impl<T, U> TryFrom<U> for T
where U: Into<T>,

type Error = Infallible

Тип, возвращаемый в случае ошибки преобразования.

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Выполняет преобразование.

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

type Error = <U as TryFrom<T>>::Error

Тип, возвращаемый в случае ошибки преобразования.

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Выполняет преобразование.

impl<T> WithSubscriber for T

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Присоединяет указанный Subscriber к этому типу и возвращает обёртку WithDispatch. Подробнее

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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API