Struct ptyprocess::PtyProcess
source · pub struct PtyProcess { /* private fields */ }
Expand description
PtyProcess controls a spawned process and communication with this.
It implements std::io::Read and std::io::Write to communicate with a child.
use ptyprocess::PtyProcess;
use std::io::Write;
use std::process::Command;
let mut process = PtyProcess::spawn(Command::new("cat")).unwrap();
process.write_all(b"Hello World").unwrap();
process.flush().unwrap();
Implementations§
source§impl PtyProcess
impl PtyProcess
sourcepub fn spawn(command: Command) -> Result<Self>
pub fn spawn(command: Command) -> Result<Self>
Spawns a child process and create a PtyProcess.
let proc = PtyProcess::spawn(Command::new("bash"));
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
fn main() -> Result<()> {
// spawn a cat process
let mut process = PtyProcess::spawn(Command::new("cat"))?;
// create a communication stream
let mut stream = process.get_raw_handle()?;
// send a message to process
writeln!(stream, "Hello cat")?;
// read a line from the stream
let mut reader = BufReader::new(stream);
let mut buf = String::new();
reader.read_line(&mut buf)?;
println!("line was entered {buf:?}");
// stop the process
assert!(process.exit(true)?);
Ok(())
}
More examples
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
fn main() {
let mut cmd = Command::new("find");
cmd.args(vec!["/home/", "-name", "foo"]);
cmd.stderr(std::process::Stdio::null());
let process = PtyProcess::spawn(cmd).unwrap();
let mut reader = BufReader::new(process.get_raw_handle().unwrap());
let mut buf = String::new();
loop {
let n = reader.read_line(&mut buf).expect("readline error");
if n == 0 {
break;
}
// by -1 we drop \n.
let text = &buf[0..buf.len() - 1];
println!("buffer: {text}");
buf.clear();
}
}
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
fn main() {
let process = PtyProcess::spawn(Command::new("cat")).expect("Error while spawning process");
let mut stream = process
.get_pty_stream()
.expect("Failed to get a pty handle");
let mut this_file = File::open(".gitignore").expect("Can't open a file");
io::copy(&mut this_file, &mut stream).expect("Can't copy a file");
// EOT
stream
.write_all(&[4])
.expect("Error while exiting a process");
// We can't read_to_end as the process isn't DEAD but at time time it is it's already a EOF
let mut buf = [0; 128];
loop {
let n = stream.read(&mut buf).expect("Erorr on read");
print!("{}", String::from_utf8_lossy(&buf[..n]));
if n == 0 {
break;
}
}
}
sourcepub fn get_raw_handle(&self) -> Result<File>
pub fn get_raw_handle(&self) -> Result<File>
Returns a file representation of a PTY, which can be used to communicate with a spawned process.
The file behaivor is platform dependent.
Safety
Be carefull changing a descriptors inner state (e.g fcntl
)
because it affects all structures which use it.
Be carefull using this method in async mode. Because descriptor is set to a non-blocking mode will affect all dublicated descriptors which may be unexpected.
Example
use ptyprocess::PtyProcess;
use std::{process::Command, io::{BufReader, LineWriter}};
let mut process = PtyProcess::spawn(Command::new("cat")).unwrap();
let pty = process.get_raw_handle().unwrap();
let mut writer = LineWriter::new(&pty);
let mut reader = BufReader::new(&pty);
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
fn main() -> Result<()> {
// spawn a cat process
let mut process = PtyProcess::spawn(Command::new("cat"))?;
// create a communication stream
let mut stream = process.get_raw_handle()?;
// send a message to process
writeln!(stream, "Hello cat")?;
// read a line from the stream
let mut reader = BufReader::new(stream);
let mut buf = String::new();
reader.read_line(&mut buf)?;
println!("line was entered {buf:?}");
// stop the process
assert!(process.exit(true)?);
Ok(())
}
More examples
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
fn main() {
let mut cmd = Command::new("find");
cmd.args(vec!["/home/", "-name", "foo"]);
cmd.stderr(std::process::Stdio::null());
let process = PtyProcess::spawn(cmd).unwrap();
let mut reader = BufReader::new(process.get_raw_handle().unwrap());
let mut buf = String::new();
loop {
let n = reader.read_line(&mut buf).expect("readline error");
if n == 0 {
break;
}
// by -1 we drop \n.
let text = &buf[0..buf.len() - 1];
println!("buffer: {text}");
buf.clear();
}
}
sourcepub fn get_pty_stream(&self) -> Result<Stream>
pub fn get_pty_stream(&self) -> Result<Stream>
Returns a stream representation of a PTY. Which can be used to communicate with a spawned process.
It differs from Self::get_raw_handle because it is platform independent.
Examples found in repository?
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
fn main() {
let process = PtyProcess::spawn(Command::new("cat")).expect("Error while spawning process");
let mut stream = process
.get_pty_stream()
.expect("Failed to get a pty handle");
let mut this_file = File::open(".gitignore").expect("Can't open a file");
io::copy(&mut this_file, &mut stream).expect("Can't copy a file");
// EOT
stream
.write_all(&[4])
.expect("Error while exiting a process");
// We can't read_to_end as the process isn't DEAD but at time time it is it's already a EOF
let mut buf = [0; 128];
loop {
let n = stream.read(&mut buf).expect("Erorr on read");
print!("{}", String::from_utf8_lossy(&buf[..n]));
if n == 0 {
break;
}
}
}
sourcepub fn get_eof_char(&self) -> u8
pub fn get_eof_char(&self) -> u8
Get a end of file character if set or a default.
sourcepub fn get_intr_char(&self) -> u8
pub fn get_intr_char(&self) -> u8
Get a interapt character if set or a default.
sourcepub fn get_window_size(&self) -> Result<(u16, u16)>
pub fn get_window_size(&self) -> Result<(u16, u16)>
Get window size of a terminal.
Default size is 80x24.
sourcepub fn set_echo(&mut self, on: bool, timeout: Option<Duration>) -> Result<bool>
pub fn set_echo(&mut self, on: bool, timeout: Option<Duration>) -> Result<bool>
Sets a echo setting for a terminal
sourcepub fn set_terminate_delay(&mut self, terminate_approach_delay: Duration)
pub fn set_terminate_delay(&mut self, terminate_approach_delay: Duration)
Set the pty process’s terminate approach delay.
sourcepub fn status(&self) -> Result<WaitStatus>
pub fn status(&self) -> Result<WaitStatus>
Status returns a status a of child process.
sourcepub fn kill(&mut self, signal: Signal) -> Result<()>
pub fn kill(&mut self, signal: Signal) -> Result<()>
Kill sends a signal to a child process.
The operation is non-blocking.
sourcepub fn wait(&self) -> Result<WaitStatus>
pub fn wait(&self) -> Result<WaitStatus>
Wait blocks until a child process exits.
It returns a error if the child was DEAD or not exist at the time of a call.
If you need to verify that a process is dead in non-blocking way you can use is_alive method.
sourcepub fn is_alive(&self) -> Result<bool>
pub fn is_alive(&self) -> Result<bool>
Checks if a process is still exists.
It’s a non blocking operation.
Keep in mind that after calling this method process might be marked as DEAD by kernel, because a check of its status. Therefore second call to Self::status or Self::is_alive might return a different status.
sourcepub fn exit(&mut self, force: bool) -> Result<bool>
pub fn exit(&mut self, force: bool) -> Result<bool>
Try to force a child to terminate.
This returns true if the child was terminated. and returns false if the child could not be terminated.
It makes 4 tries getting more thorough.
- SIGHUP
- SIGCONT
- SIGINT
- SIGTERM
If “force” is true
then moves onto SIGKILL.
Examples found in repository?
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
fn main() -> Result<()> {
// spawn a cat process
let mut process = PtyProcess::spawn(Command::new("cat"))?;
// create a communication stream
let mut stream = process.get_raw_handle()?;
// send a message to process
writeln!(stream, "Hello cat")?;
// read a line from the stream
let mut reader = BufReader::new(stream);
let mut buf = String::new();
reader.read_line(&mut buf)?;
println!("line was entered {buf:?}");
// stop the process
assert!(process.exit(true)?);
Ok(())
}