Help with the Thrussh crate

Learning a new rust crate "Thrussh". wanted to see if anyone is familiar with this crate to help me out. i just can't seem to figure out why the server is not sending me the command output

here is the output i get while running the code below

Success
logged in successfully
WindowAdjusted { new_size: 2097152 }
hello

here is the complete code

use tokio;
use std::sync::Arc;
use std::future;
use thrussh::{
    self,
    ChannelId,
    ChannelOpenFailure,
    client::{self, Config, Session, Handle},
};
use anyhow;
use env_logger;
use thrussh_keys::key;

struct SSHClient {}

impl client::Handler for SSHClient {
    type Error = anyhow::Error;
    type FutureBool = future::Ready<Result<(Self, bool), anyhow::Error>>;
    type FutureUnit = future::Ready<Result<(Self, client::Session), anyhow::Error>>;

    fn  finished_bool(self, b: bool) -> Self::FutureBool {
         future::ready(Ok((self, b)))
    }

    fn finished(self, session: client::Session) -> Self::FutureUnit {
        future::ready(Ok((self, session)))
    }

    fn check_server_key(self, server_public_key: &key::PublicKey) -> Self::FutureBool {
        self.finished_bool(true)
    }

    fn channel_open_failure(self, channel: ChannelId, reason: ChannelOpenFailure, description: &str, language: &str, mut session: Session) -> Self::FutureUnit {
        println!("Failed to open channel");
        future::ready(Err(anyhow::anyhow!("Failed")))
    }

    fn data(self, channel: ChannelId, data: &[u8], session: Session) -> Self::FutureUnit {
        println!("message received {:?}", data);
        self.finished(session)
    }

}


#[tokio::main]
async fn main() -> (){
    env_logger::init();
    // use default configuration
    let config = Config::default();
    let config = Arc::new(config);
    let mvp: SSHClient = SSHClient{};
    let mut session: Handle<SSHClient>;

    // connect to ssh
    match thrussh::client::connect(config, "localhost:22", mvp).await {
        Ok(sess) => {
            session = sess;
            println!("Success");
        },
        Err(err) => {
            println!("Failed {}", err);
            std::process::exit(1);
        }
    }


    if session.authenticate_password("username", "password").await.is_ok() {
        println!("logged in successfully");
    } else {
        println!("login failed", );
    }

    let mut channel = session.channel_open_session().await.unwrap();
    channel.request_shell(true).await.unwrap();
    channel.exec(false, "tail -f /var/log/messages").await.unwrap();
    let chmsg =  channel.wait().await.unwrap();

    println!("{:?}", chmsg);
    println!("hello");
}

Try receiving messages using channel.wait() in a loop. One command may result in multiple messages being sent. In your case the first one is WindowAdjusted it seems.

updated the loop section to this, so i can see what is going on

     loop {
        let chmsg =  channel.wait().await.unwrap();
       
        match chmsg {
            thrussh::ChannelMsg::Data{data} => { 
                let new_data = std::str::from_utf8(data.as_ref()).unwrap();
                println!("Data receiveed::  {}", new_data);
            },
            thrussh::ChannelMsg::WindowAdjusted{new_size} => println!("WindowAdjusted"),
            thrussh::ChannelMsg::Success => println!("Success"), 
            thrussh::ChannelMsg::Eof  => println!("Eof"), 
            thrussh::ChannelMsg::Close => println!("Close"), 
            // thrussh::ChannelMsg::ExitSignal{} => println!("exitstatus"), 
            thrussh::ChannelMsg::ExtendedData{data, ext} => println!("ExtendedData"), 
            _ => { println!("Something activated thIs match arm"); }
        }
    }

output

Success
logged in successfully
WindowAdjusted
Success
message received "Last failed login: Mon Jun 14 01:40:24 MDT 2021 from ::1 on ssh:notty\nThere were 3 failed login attempts since the last successful login.\n"

the last line is from the data event handler

    fn data(self, channel: ChannelId, data: &[u8], session: Session) -> Self::FutureUnit {
        let new_data = std::str::from_utf8(data).unwrap();
        println!("message received {:?}", &new_data);
        self.finished(session)
    }

I had to read the SSH spec to understand why my code was not working

https://datatracker.ietf.org/doc/html/rfc4254#section-6.5

from my code i was requesting a shell and exec using the same channel. accoring to the spec ""Only one of these requests can succeed per channel"""

commented out the shell request and i was able to get reply

    let mut channel = session.channel_open_session().await.unwrap();
    // channel.request_shell(true).await.unwrap(); 
    channel.exec(true, "ls -l /").await.unwrap();

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.