Running multiple SSH client sessions using russh

Hello,

I wonder if anybody has experience in using russh.

I successfully run the client example. Now I'm trying to figure out how to run multiple programs at the same time which I think should be possible.

There are 3 stages:

Session::connect()                       // connect over SSH
session.session.channel_open_session()   // returns handle to a session channel
channel.exec()                           // executes a program

I tried to clone session and channel and none of them are clonable which means I can't tokio::task::spawn it to execute multiple programs. The only thing I can spawn is the whole thing (including Session::connect()) which is like typing ssh user@host several times and I'd quickly hit limits if I tried that...

Thank you.

I don't have any experience with russh, but from a quick glance at Handle::open_session, it looks to me like opening a new session is a light-weight operation, suitable for running multiple sessions through the same Handle. You could share the Handle with an Arc between tasks, or create a new channel and pass that to your task by value.

1 Like

Thank you @jofas

Unfortunately session (created by Session::connect()) and channel (created by session.channel_open_session()) must be mutable. I can put it into Arc and Mutex but then the Mutex will need to stay locked for the whole duration of a spawned thread...

Okay so what about my second proposal,

where you create a new channel for each task you spawn via Handle::open_session? When you pass a channel by value to a task, the task takes ownership of that channel. This allows the task to mutate the channel independently from any other channel some other task might be mutating simultaneously.

1 Like

That works! Thank you @jofas :kissing_heart:

For anybody reading this, if you need an explanation like you're 5 (which is what I need :wink: ):

Outside a for loop connect to a server:

let mut session = Session::connect(...

Then inside a for loop:

let mut channel = session.open().await;
let handle = tokio::task::spawn(async move {
  Session::call(&mut channel...
1 Like

Hello, I see you're new to the forum. Since the problem is solved, please mark their reply as the solution (check box at the bottom of the reply) since they answered it for you. This also tells others that the topic is resolved. Thanks.

1 Like