Open chama-chomo opened 4 years ago
as a Rust newbie I was able to create kind of a POC for my ssh repl, my only problem is it doesn't feel very much like a standard ssh session with command/path expansion and so. There is definitely a better way. Nevertheless, I'm going to provide my piece of code for someone like me, as inspiration (this is my specific case ofc, not too much generic)..
...
fn connect_ssh(&self, dest: Option<&String>) -> Result<()> {
ConnectAction::do_ssh_repl(&dest.unwrap())
.unwrap_or_else(|e| panic!("ssh session failed with {}", e));
Ok(())
}
fn do_ssh_repl(host: &String) -> Result<()> {
let mut ssh = ConnectAction::create_ssh_session(&host)?;
ssh.exp_regex("\r\n.*root.*:~# ")?;
ConnectAction::interact(&mut ssh)?;
ssh.exp_eof()?;
Ok(())
}
fn create_ssh_session(host: &String) -> Result<PtyReplSession> {
println!("Connecting to host {}", host);
let custom_prompt = format!("root@{}'s password: ", host);
let custom_command = format!("ssh root@{}", host);
let mut ssh = PtyReplSession {
echo_on: false,
prompt: custom_prompt,
pty_session: spawn(&*custom_command.into_boxed_str(), Some(5000))?,
quit_command: Some("Q".to_string()),
};
ssh.wait_for_prompt()?;
ssh.send_line("root")?;
Ok(ssh)
}
fn interact(session: &mut PtyReplSession) -> Result<()> {
while let Some(WaitStatus::StillAlive) = session.process.status() {
let mut user_input = String::new();
print!("ssh session :> ");
io::stdout().flush().expect("couldn't flush buffer");
io::stdin().read_line(&mut user_input).expect("error: unable to read user input");
session.writer.write(&user_input.into_bytes()).expect("could not write");
let re = Regex::new(r".*root@.*:~# ").unwrap();
let (before, _) = session.reader.read_until(&rexpect::ReadUntil::Regex(re)).unwrap();
println!("{}", before);
};
Ok(())
}
@chama-chomo, your workaround looks good, but it's still not perfect. For example, if I start gdb task with rexpect, i want a real gdb tty after calling interact. But in this way, it can't offer me that. This issue is opened two years before, but no updates for it. I will use pexpect for my tools. Life is short, I use python.^v^
We've implemented an interact
functionality in the pixi
package manager (to spawn an interactive shell where we can source some scripts after the shell has started, and then give control to the user).
You can have a look at the code here: https://github.com/prefix-dev/pixi/pull/316/files
There were some changes:
raw
modeECHO
for the terminal (to see what user types) - this is always deactivated in rexpectSIGWINCH
signal happensselect
on the two filestreams (stdin of the parent and stdout of the child) to forward the input / outputWe've gone through a few iterations with this code and are reasonably happy with it now. I am not sure what the appetite is for these changes in rexpect
. They are a bit deeper (especially with the ECHO
part), but we could potentially make a PR to contribute the feature.
Is there any way to return control of the terminal back to the user ? e.g. after connecting to a remote server. Thanks. In python
pexpect
I useinteract()
method to achieve this.