pub fn spawn_bash(timeout: Option<u64>) -> Result<PtyReplSession, Error>Expand description
Spawn bash in a pty session, run programs and expect output
The difference to spawn and spawn_command is:
spawn_bashstarts bash with a custom rcfile which guarantees a certain prompt- the
PtyBashSessionalso provideswait_for_promptandexecute
timeout: the duration until which exp_* returns a timeout error, or None
additionally, when dropping the bash prompt while bash is still blocked by a program
(e.g. sleep 9999) then the timeout is used as a timeout before a kill -9 is issued
at the bash command. Use a timeout whenever possible because it makes
debugging a lot easier (otherwise the program just hangs and you
don’t know where)
bash is started with echo off. That means you don’t need to “read back”
what you wrote to bash. But what you need to do is a wait_for_prompt
after a process finished.
Also: if you start a program you should use execute and not send_line.
For an example see the README
Examples found in repository?
4fn main() -> Result<(), Error> {
5 let mut p = spawn_bash(Some(1000))?;
6 p.execute("ping 8.8.8.8", "bytes")?;
7 p.send_control('z')?;
8 p.wait_for_prompt()?;
9 // bash writes 'ping 8.8.8.8' to stdout again to state which job was put into background
10 p.execute("bg", "ping 8.8.8.8")?;
11 p.wait_for_prompt()?;
12 p.send_line("sleep 0.5")?;
13 p.wait_for_prompt()?;
14 // bash writes 'ping 8.8.8.8' to stdout again to state which job was put into foreground
15 p.execute("fg", "ping 8.8.8.8")?;
16 p.send_control('c')?;
17 p.exp_string("packet loss")?;
18 Ok(())
19}More examples
4fn main() -> Result<(), Error> {
5 let mut p = spawn_bash(Some(2000))?;
6
7 // case 1: wait until program is done
8 p.send_line("hostname")?;
9 let hostname = p.read_line()?;
10 p.wait_for_prompt()?; // go sure `hostname` is really done
11 println!("Current hostname: {hostname}");
12
13 // case 2: wait until done, only extract a few infos
14 p.send_line("wc /etc/passwd")?;
15 // `exp_regex` returns both string-before-match and match itself, discard first
16 let (_, lines) = p.exp_regex("[0-9]+")?;
17 let (_, words) = p.exp_regex("[0-9]+")?;
18 let (_, bytes) = p.exp_regex("[0-9]+")?;
19 p.wait_for_prompt()?; // go sure `wc` is really done
20 println!("/etc/passwd has {lines} lines, {words} words, {bytes} chars");
21
22 // case 3: read while program is still executing
23 p.execute("ping 8.8.8.8", "bytes of data")?; // returns when it sees "bytes of data" in output
24 for _ in 0..5 {
25 // times out if one ping takes longer than 2s
26 let (_, duration) = p.exp_regex("[0-9. ]+ ms")?;
27 println!("Roundtrip time: {duration}");
28 }
29 p.send_control('c')?;
30 Ok(())
31}