Spec-Zone.ru › Tokio

Структура Child

pub struct Child {
    pub stdin: Option<ChildStdin>,
    pub stdout: Option<ChildStdout>,
    pub stderr: Option<ChildStderr>,
    /* private fields */
}
Доступно только при включённой возможности crate process.

Представление дочернего процесса, запущенного в цикле обработки событий.

Особенности

Как и в стандартной библиотеке, в отличие от парадигмы futures, согласно которой удаление подразумевает отмену, запущенный процесс по умолчанию продолжит выполняться, даже если дескриптор Child был удалён.

Метод Command::kill_on_drop можно использовать, чтобы изменить это поведение и завершить дочерний процесс, если обёртка Child удалена до его завершения.

Поля

stdin: Option<ChildStdin>

Дескриптор для записи в стандартный ввод дочернего процесса (stdin), если он был перехвачен. Чтобы избежать частичного перемещения child и, как следствие, невозможности вызывать функции для child при использовании stdin, может быть полезно сделать следующее:

let stdin = child.stdin.take().unwrap();
stdout: Option<ChildStdout>

Дескриптор для чтения из стандартного вывода дочернего процесса (stdout), если он был перехвачен. Может быть полезно сделать следующее:

let stdout = child.stdout.take().unwrap();

чтобы избежать частичного перемещения child и, как следствие, невозможности вызывать функции для child при использовании stdout.

stderr: Option<ChildStderr>

Дескриптор для чтения из стандартного потока ошибок дочернего процесса (stderr), если он был перехвачен. Может быть полезно сделать следующее:

let stderr = child.stderr.take().unwrap();

чтобы избежать частичного перемещения child и, как следствие, невозможности вызывать функции для child при использовании stderr.

Реализации

impl Child

pub fn id(&self) -> Option<u32>

Возвращает назначенный операционной системой идентификатор процесса, связанный с этим дочерним процессом, пока он продолжает выполняться.

После завершения дочернего процесса этот метод будет возвращать None. Это сделано, чтобы избежать путаницы на таких платформах, как Unix, где идентификатор операционной системы может быть повторно использован после завершения процесса.

pub fn raw_handle(&self) -> Option<RawHandle>

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

Извлекает необработанный дескриптор процесса, связанного с этим дочерним процессом, пока он продолжает выполняться. Возвращает None, если дочерний процесс завершился.

pub fn start_kill(&mut self) -> Result<()>

Пытается принудительно завершить дочерний процесс, но не дожидается выполнения запроса.

На платформах Unix это эквивалентно отправке SIGKILL. Обратите внимание, что на платформах Unix после отправки сигнала завершения может остаться процесс-зомби; чтобы этого избежать, вызывающая сторона должна убедиться, что успешно вызван либо child.wait().await, либо child.try_wait().

pub async fn kill(&mut self) -> Result<()>

Принудительно завершает дочерний процесс.

На платформах unix это эквивалентно отправке SIGKILL, за которой следует wait.

Обратите внимание: версия std метода Child::kill не wait. Для эквивалента Child::kill в стандартной библиотеке используйте start_kill.

Примеры

Если дочерний процесс нужно завершить удалённо, это можно сделать с помощью комбинации макроса select! и канала oneshot. В следующем примере дочерний процесс будет выполняться до завершения, если только в канал oneshot не будет отправлено сообщение. Если это произойдёт, дочерний процесс будет немедленно завершён с помощью метода .kill().

use tokio::process::Command;
use tokio::sync::oneshot::channel;

#[tokio::main]
async fn main() {
    let (send, recv) = channel::<()>();
    let mut child = Command::new("sleep").arg("1").spawn().unwrap();
    tokio::spawn(async move { send.send(()) });
    tokio::select! {
        _ = child.wait() => {}
        _ = recv => child.kill().await.expect("kill failed"),
    }
}

Вы также можете взаимодействовать со стандартными потоками ввода-вывода дочернего процесса. Например, можно читать его stdout, пока вы ожидаете его завершения.


#[tokio::main]
async fn main() {
    let (_tx, rx) = channel::<()>();

    let mut child = Command::new("echo")
        .arg("Hello World!")
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();

    let mut stdout = child.stdout.take().expect("stdout is not captured");

    let read_stdout = tokio::spawn(async move {
        let mut buff = Vec::new();
        let _ = stdout.read_to_end(&mut buff).await;

        buff
    });

    tokio::select! {
        _ = child.wait() => {}
        _ = rx => { child.kill().await.expect("kill failed") },
    }

    let buff = read_stdout.await.unwrap();

    assert_eq!(buff, b"Hello World!\n");
}

pub async fn wait(&mut self) -> Result<ExitStatus>

Ожидает полного завершения дочернего процесса и возвращает статус завершения. После первого вызова эта функция будет возвращать одно и то же значение.

Перед ожиданием будет закрыт дескриптор stdin дочернего процесса, если он есть. Это помогает избежать взаимной блокировки: дочерний процесс не будет ожидать ввод от родительского процесса, пока родительский процесс ожидает завершения дочернего.

Если вызывающая сторона хочет самостоятельно управлять моментом закрытия дескриптора stdin дочернего процесса, она может закрыть .take() перед вызовом .wait():

Безопасность при отмене

Эту функцию можно безопасно отменять.

use tokio::io::AsyncWriteExt;
use tokio::process::Command;
use std::process::Stdio;

#[tokio::main]
async fn main() {
    let mut child = Command::new("cat")
        .stdin(Stdio::piped())
        .spawn()
        .unwrap();

    let mut stdin = child.stdin.take().unwrap();
    tokio::spawn(async move {
        // do something with stdin here...
        stdin.write_all(b"hello world\n").await.unwrap();

        // then drop when finished
        drop(stdin);
    });

    // wait for the process to complete
    let _ = child.wait().await;
}

pub fn try_wait(&mut self) -> Result<Option<ExitStatus>>

Пытается получить статус завершения дочернего процесса, если он уже завершился.

Эта функция не блокирует вызывающий поток и только проверяет, завершился ли дочерний процесс. Если дочерний процесс завершился, то в Unix идентификатор процесса освобождается. Гарантируется, что эта функция будет снова возвращать успешный статус завершения, если дочерний процесс уже завершился.

Если дочерний процесс завершился, возвращается Ok(Some(status)). Если статус завершения пока недоступен, возвращается Ok(None). При возникновении ошибки возвращается эта ошибка.

Обратите внимание: в отличие от wait, эта функция не пытается закрыть stdin и не пробуждает текущую задачу при завершении дочернего процесса.

pub async fn wait_with_output(self) -> Result<Output>

Возвращает future, который завершится значением Output, содержащим код завершения, stdout и stderr дочернего процесса.

Возвращённый future одновременно ожидает завершения дочернего процесса и собирает весь оставшийся вывод из дескрипторов stdout/stderr, возвращая экземпляр Output.

Дескриптор stdin дочернего процесса, если он есть, будет закрыт перед ожиданием. Это помогает избежать взаимной блокировки: так гарантируется, что дочерний процесс не будет заблокирован в ожидании ввода от родительского процесса, пока родительский процесс ожидает завершения дочернего.

По умолчанию stdin, stdout и stderr наследуются от родительского процесса. Чтобы перехватить вывод в этот Output, необходимо создать новые каналы между родительским и дочерним процессами. При создании Command используйте соответственно stdout(Stdio::piped()) или stderr(Stdio::piped()).

Реализации трейтов

impl Debug for Child

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

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

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

impl !RefUnwindSafe for Child

impl !UnwindSafe for Child

impl Freeze for Child

impl Send for Child

impl Sync for Child

impl Unpin for Child

impl UnsafeUnpin for Child

Общие реализации

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.Child.html

Spec-Zone.ru

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