Struct PtyProcess

Source
pub struct PtyProcess {
    pub pty: PtyMaster,
    pub child_pid: Pid,
    /* private fields */
}
Expand description

Start a process in a forked tty so you can interact with it the same as you would within a terminal

The process and pty session are killed upon dropping PtyProcess

§Example

Typically you want to do something like this (for a more complete example see unit test test_cat within this module):


use rexpect::process::PtyProcess;
use std::process::Command;
use std::fs::File;
use std::io::{BufReader, LineWriter};
use std::os::unix::io::{FromRawFd, AsRawFd};
use nix::unistd::dup;


let mut process = PtyProcess::new(Command::new("cat")).expect("could not execute cat");
let fd = dup(&process.pty).unwrap();
let f = File::from(fd);
let mut writer = LineWriter::new(&f);
let mut reader = BufReader::new(&f);
process.exit().expect("could not terminate process");

// writer.write() sends strings to `cat`
// writer.reader() reads back what `cat` wrote
// send Ctrl-C with writer.write(&[3]) and writer.flush()

Fields§

§pty: PtyMaster§child_pid: Pid

Implementations§

Source§

impl PtyProcess

Source

pub fn new(command: Command) -> Result<Self, Error>

Start a process in a forked pty

Source

pub fn get_file_handle(&self) -> Result<File, Error>

Get handle to pty fork for reading/writing

Source

pub fn set_kill_timeout(&mut self, timeout_ms: Option<u64>)

At the drop of PtyProcess the running process is killed. This is blocking forever if the process does not react to a normal kill. If kill_timeout is set the process is kill -9ed after duration

Source

pub fn status(&self) -> Option<WaitStatus>

Get status of child process, non-blocking.

This method runs waitpid on the process. This means: If you ran exit() before or status() this method will return None

§Example

use rexpect::process::{self, wait::WaitStatus};
use std::process::Command;

let cmd = Command::new("/path/to/myprog");
let process = process::PtyProcess::new(cmd).expect("could not execute myprog");
while let Some(WaitStatus::StillAlive) = process.status() {
    // do something
}
Source

pub fn wait(&self) -> Result<WaitStatus, Error>

Wait until process has exited. This is a blocking call. If the process doesn’t terminate this will block forever.

Examples found in repository?
examples/exit_code.rs (line 11)
9fn main() -> Result<(), Error> {
10    let p = spawn("cat /etc/passwd", Some(2000))?;
11    match p.process.wait() {
12        Ok(wait::WaitStatus::Exited(_, 0)) => println!("cat exited with code 0, all good!"),
13        _ => println!("cat exited with code >0, or it was killed"),
14    }
15
16    let mut p = spawn("cat /this/does/not/exist", Some(2000))?;
17    match p.process.wait() {
18        Ok(wait::WaitStatus::Exited(_, 0)) => println!("cat succeeded"),
19        Ok(wait::WaitStatus::Exited(_, c)) => {
20            println!("Cat failed with exit code {c}");
21            println!("Output (stdout and stderr): {}", p.exp_eof()?);
22        }
23        // for other possible return types of wait()
24        // see here: https://tailhook.github.io/rotor/nix/sys/wait/enum.WaitStatus.html
25        _ => println!("cat was probably killed"),
26    }
27
28    Ok(())
29}
Source

pub fn exit(&mut self) -> Result<WaitStatus, Error>

Regularly exit the process, this method is blocking until the process is dead

Source

pub fn signal(&mut self, sig: Signal) -> Result<(), Error>

Non-blocking variant of kill() (doesn’t wait for process to be killed)

Source

pub fn kill(&mut self, sig: Signal) -> Result<WaitStatus, Error>

Kill the process with a specific signal. This method blocks, until the process is dead

repeatedly sends SIGTERM to the process until it died, the pty session is closed upon dropping PtyMaster, so we don’t need to explicitly do that here.

if kill_timeout is set and a repeated sending of signal does not result in the process being killed, then kill -9 is sent after the kill_timeout duration has elapsed.

Trait Implementations§

Source§

impl Drop for PtyProcess

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

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

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

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

Source§

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

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

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

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

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

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

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

Performs the conversion.
Source§

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

Source§

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

The type returned in the event of a conversion error.
Source§

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

Performs the conversion.