pub struct Channel { /* private fields */ }
Expand description
Represents a channel in a Session
.
A Session
can have multiple channels; there is typically one
for the shell/program being run, but additional channels can
be opened to forward TCP or other connections.
open_session is often the first
thing you will call on the Channel
after creating it; this establishes
the channel for executing commands.
Then you will typically use either request_exec to run a non-interactive command, or request_pty followed request_shell to set up an interactive remote shell.
§Thread Safety
Channel
is strongly associated with the Session
to which it belongs.
libssh doesn’t allow using anything associated with a given Session
from multiple threads concurrently. These Rust bindings encapsulate
the underlying Session
in an internal mutex, which allows you to
safely operate on the various elements of the session and even move
them to other threads, but you need to be aware that calling methods
on any of those structs will attempt to lock the underlying session,
and this can lead to blocking in surprising situations.
Implementations§
Source§impl Channel
impl Channel
Sourcepub fn accept_x11(&self, timeout: Duration) -> Option<Self>
pub fn accept_x11(&self, timeout: Duration) -> Option<Self>
Accept an X11 forwarding channel.
Returns a newly created Channel
, or None
if no X11 request from the server.
Sourcepub fn close(&self) -> SshResult<()>
pub fn close(&self) -> SshResult<()>
Close a channel. This sends an end of file and then closes the channel. You won’t be able to recover any data the server was going to send or was in buffers.
Sourcepub fn get_exit_status(&self) -> Option<c_int>
pub fn get_exit_status(&self) -> Option<c_int>
Get the exit status of the channel (error code from the executed instruction). This function may block until a timeout (or never) if the other side is not willing to close the channel.
Examples found in repository?
107fn main() -> SshResult<()> {
108 let sess = Session::new()?;
109 sess.set_auth_callback(|prompt, echo, verify, identity| {
110 let prompt = match identity {
111 Some(ident) => format!("{} ({}): ", prompt, ident),
112 None => prompt.to_string(),
113 };
114 get_input(&prompt, None, echo, verify)
115 .ok_or_else(|| Error::Fatal("reading password".to_string()))
116 });
117
118 sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119 // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120 sess.options_parse_config(None)?;
121 sess.connect()?;
122 eprintln!(
123 "using {} as user name for authentication",
124 sess.get_user_name()?
125 );
126 verify_known_hosts(&sess)?;
127
128 authenticate(&sess, None)?;
129
130 let channel = sess.new_channel()?;
131 channel.open_session()?;
132 channel.request_exec("whoami")?;
133 channel.send_eof()?;
134
135 let mut stdout = String::new();
136 channel.stdout().read_to_string(&mut stdout)?;
137
138 eprintln!("whoami -> {}", stdout);
139
140 let res = channel.get_exit_status();
141 eprintln!("exit status: {:?}", res);
142
143 Ok(())
144}
Sourcepub fn get_exit_signal(&self) -> Option<SignalState>
pub fn get_exit_signal(&self) -> Option<SignalState>
Get the exit signal status of the channel. If the channel was closed/terminated due to a signal, and the remote system supports the signal concept, the signal state will be set and reported here.
Sourcepub fn send_eof(&self) -> SshResult<()>
pub fn send_eof(&self) -> SshResult<()>
Send an end of file on the channel.
You should call this when you have no additional data to send to the channel to signal that information to the remote host.
This doesn’t close the channel. You may still read from it but not write.
Examples found in repository?
107fn main() -> SshResult<()> {
108 let sess = Session::new()?;
109 sess.set_auth_callback(|prompt, echo, verify, identity| {
110 let prompt = match identity {
111 Some(ident) => format!("{} ({}): ", prompt, ident),
112 None => prompt.to_string(),
113 };
114 get_input(&prompt, None, echo, verify)
115 .ok_or_else(|| Error::Fatal("reading password".to_string()))
116 });
117
118 sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119 // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120 sess.options_parse_config(None)?;
121 sess.connect()?;
122 eprintln!(
123 "using {} as user name for authentication",
124 sess.get_user_name()?
125 );
126 verify_known_hosts(&sess)?;
127
128 authenticate(&sess, None)?;
129
130 let channel = sess.new_channel()?;
131 channel.open_session()?;
132 channel.request_exec("whoami")?;
133 channel.send_eof()?;
134
135 let mut stdout = String::new();
136 channel.stdout().read_to_string(&mut stdout)?;
137
138 eprintln!("whoami -> {}", stdout);
139
140 let res = channel.get_exit_status();
141 eprintln!("exit status: {:?}", res);
142
143 Ok(())
144}
Sourcepub fn open_auth_agent(&self) -> SshResult<()>
pub fn open_auth_agent(&self) -> SshResult<()>
Open an agent authentication forwarding channel. This type of channel can be opened by a server towards a client in order to provide SSH-Agent services to the server-side process. This channel can only be opened if the client claimed support by sending a channel request beforehand.
Sourcepub fn request_auth_agent(&self) -> SshResult<()>
pub fn request_auth_agent(&self) -> SshResult<()>
Send an "auth-agent-req"
channel request over an existing session channel.
This client-side request will enable forwarding the agent over a secure tunnel. When the server is ready to open one authentication agent channel, an ssh_channel_open_request_auth_agent_callback event will be generated.
Sourcepub fn request_env(&self, name: &str, value: &str) -> SshResult<()>
pub fn request_env(&self, name: &str, value: &str) -> SshResult<()>
Set environment variable. Some environment variables may be refused by security reasons.
Sourcepub fn request_shell(&self) -> SshResult<()>
pub fn request_shell(&self) -> SshResult<()>
Requests a shell; asks the server to spawn the user’s shell, rather than directly executing a command specified by the client.
The channel must be a session channel; you need to have called open_session before this will succeed.
Sourcepub fn request_exec(&self, command: &str) -> SshResult<()>
pub fn request_exec(&self, command: &str) -> SshResult<()>
Run a shell command without an interactive shell. This is similar to ‘sh -c command’.
The channel must be a session channel; you need to have called open_session before this will succeed.
Examples found in repository?
107fn main() -> SshResult<()> {
108 let sess = Session::new()?;
109 sess.set_auth_callback(|prompt, echo, verify, identity| {
110 let prompt = match identity {
111 Some(ident) => format!("{} ({}): ", prompt, ident),
112 None => prompt.to_string(),
113 };
114 get_input(&prompt, None, echo, verify)
115 .ok_or_else(|| Error::Fatal("reading password".to_string()))
116 });
117
118 sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119 // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120 sess.options_parse_config(None)?;
121 sess.connect()?;
122 eprintln!(
123 "using {} as user name for authentication",
124 sess.get_user_name()?
125 );
126 verify_known_hosts(&sess)?;
127
128 authenticate(&sess, None)?;
129
130 let channel = sess.new_channel()?;
131 channel.open_session()?;
132 channel.request_exec("whoami")?;
133 channel.send_eof()?;
134
135 let mut stdout = String::new();
136 channel.stdout().read_to_string(&mut stdout)?;
137
138 eprintln!("whoami -> {}", stdout);
139
140 let res = channel.get_exit_status();
141 eprintln!("exit status: {:?}", res);
142
143 Ok(())
144}
Sourcepub fn request_subsystem(&self, subsys: &str) -> SshResult<()>
pub fn request_subsystem(&self, subsys: &str) -> SshResult<()>
Request a subsystem.
You probably don’t need this unless you know what you are doing!
Sourcepub fn request_pty(&self, term: &str, columns: u32, rows: u32) -> SshResult<()>
pub fn request_pty(&self, term: &str, columns: u32, rows: u32) -> SshResult<()>
Request a PTY with a specific type and size. A PTY is useful when you want to run an interactive program on the remote host.
term
is the initial value for the TERM
environment variable.
If you’re not sure what to fill for the values,
term = "xterm"
, columns = 80
and rows = 24
are reasonable
defaults.
Sourcepub fn change_pty_size(&self, columns: u32, rows: u32) -> SshResult<()>
pub fn change_pty_size(&self, columns: u32, rows: u32) -> SshResult<()>
Informs the server that the local size of the PTY has changed
Sourcepub fn request_send_break(&self, length: Duration) -> SshResult<()>
pub fn request_send_break(&self, length: Duration) -> SshResult<()>
Send a break signal to the server (as described in RFC 4335). Sends a break signal to the remote process. Note, that remote system may not support breaks. In such a case this request will be silently ignored.
Sourcepub fn request_send_signal(&self, signal: &str) -> SshResult<()>
pub fn request_send_signal(&self, signal: &str) -> SshResult<()>
Send a signal to remote process (as described in RFC 4254, section 6.9). Sends a signal to the remote process. Note, that remote system may not support signals concept. In such a case this request will be silently ignored.
signal
is the name of the signal, without the "SIG"
prefix.
For example, "ABRT"
, "INT"
, "KILL"
and so on.
The OpenSSH server has only supported signals since OpenSSH version 8.1, released in 2019. https://bugzilla.mindrot.org/show_bug.cgi?id=1424
Sourcepub fn open_forward(
&self,
remote_host: &str,
remote_port: u16,
source_host: &str,
source_port: u16,
) -> SshResult<()>
pub fn open_forward( &self, remote_host: &str, remote_port: u16, source_host: &str, source_port: u16, ) -> SshResult<()>
Open a TCP/IP forwarding channel.
remote_host
, remote_port
identify the destination for the
connection.
source_host
, source_port
identify the origin of the connection
on the client side; these are used primarily for logging purposes.
This function does not bind the source port and does not automatically forward the content of a socket to the channel. You still have to read/write this channel object to achieve that.
Sourcepub fn open_forward_unix(
&self,
remote_path: &str,
source_host: &str,
source_port: u16,
) -> SshResult<()>
pub fn open_forward_unix( &self, remote_path: &str, source_host: &str, source_port: u16, ) -> SshResult<()>
Open a UNIX domain socket forwarding channel.
remote_path
is the path to the unix socket to open on the remote
machine.
source_host
and source_port
identify the originating connection
from the client machine and are used for logging purposes.
This function does not bind the source and does not automatically forward the content of a socket to the channel. You still have to read/write this channel object to achieve that.
Sourcepub fn request_x11(
&self,
single_connection: bool,
protocol: Option<&str>,
cookie: Option<&str>,
screen_number: c_int,
) -> SshResult<()>
pub fn request_x11( &self, single_connection: bool, protocol: Option<&str>, cookie: Option<&str>, screen_number: c_int, ) -> SshResult<()>
Sends the "x11-req"
channel request over an existing session channel.
This will enable redirecting the display of the remote X11 applications
to local X server over an secure tunnel.
Sourcepub fn open_session(&self) -> SshResult<()>
pub fn open_session(&self) -> SshResult<()>
Open a session channel (suited for a shell, not TCP forwarding).
Examples found in repository?
107fn main() -> SshResult<()> {
108 let sess = Session::new()?;
109 sess.set_auth_callback(|prompt, echo, verify, identity| {
110 let prompt = match identity {
111 Some(ident) => format!("{} ({}): ", prompt, ident),
112 None => prompt.to_string(),
113 };
114 get_input(&prompt, None, echo, verify)
115 .ok_or_else(|| Error::Fatal("reading password".to_string()))
116 });
117
118 sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119 // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120 sess.options_parse_config(None)?;
121 sess.connect()?;
122 eprintln!(
123 "using {} as user name for authentication",
124 sess.get_user_name()?
125 );
126 verify_known_hosts(&sess)?;
127
128 authenticate(&sess, None)?;
129
130 let channel = sess.new_channel()?;
131 channel.open_session()?;
132 channel.request_exec("whoami")?;
133 channel.send_eof()?;
134
135 let mut stdout = String::new();
136 channel.stdout().read_to_string(&mut stdout)?;
137
138 eprintln!("whoami -> {}", stdout);
139
140 let res = channel.get_exit_status();
141 eprintln!("exit status: {:?}", res);
142
143 Ok(())
144}
Sourcepub fn poll_timeout(
&self,
is_stderr: bool,
timeout: Option<Duration>,
) -> SshResult<PollStatus>
pub fn poll_timeout( &self, is_stderr: bool, timeout: Option<Duration>, ) -> SshResult<PollStatus>
Polls a channel for data to read.
Returns the number of bytes available for reading.
If timeout
is None, then blocks until data is available.
Sourcepub fn read_timeout(
&self,
buf: &mut [u8],
is_stderr: bool,
timeout: Option<Duration>,
) -> SshResult<usize>
pub fn read_timeout( &self, buf: &mut [u8], is_stderr: bool, timeout: Option<Duration>, ) -> SshResult<usize>
Reads data from a channel. This function may fewer bytes than the buf size.
Sourcepub fn read_nonblocking(
&self,
buf: &mut [u8],
is_stderr: bool,
) -> SshResult<usize>
pub fn read_nonblocking( &self, buf: &mut [u8], is_stderr: bool, ) -> SshResult<usize>
Do a nonblocking read on the channel. A nonblocking read on the specified channel. it will return <= count bytes of data read atomically.
Sourcepub fn window_size(&self) -> usize
pub fn window_size(&self) -> usize
Get the remote window size. This is the maximum amounts of bytes the remote side expects us to send before growing the window again. A nonzero return value does not guarantee the socket is ready to send that much data. Buffering may happen in the local SSH packet buffer, so beware of really big window sizes. A zero return value means that a write will block (if the session is in blocking mode) until the window grows back.
Sourcepub fn stdout(&self) -> impl Read + '_
pub fn stdout(&self) -> impl Read + '_
Returns a struct that implements std::io::Read
and that will read data from the stdout channel.
Examples found in repository?
107fn main() -> SshResult<()> {
108 let sess = Session::new()?;
109 sess.set_auth_callback(|prompt, echo, verify, identity| {
110 let prompt = match identity {
111 Some(ident) => format!("{} ({}): ", prompt, ident),
112 None => prompt.to_string(),
113 };
114 get_input(&prompt, None, echo, verify)
115 .ok_or_else(|| Error::Fatal("reading password".to_string()))
116 });
117
118 sess.set_option(SshOption::Hostname("localhost".to_string()))?;
119 // sess.set_option(SshOption::LogLevel(LogLevel::Packet))?;
120 sess.options_parse_config(None)?;
121 sess.connect()?;
122 eprintln!(
123 "using {} as user name for authentication",
124 sess.get_user_name()?
125 );
126 verify_known_hosts(&sess)?;
127
128 authenticate(&sess, None)?;
129
130 let channel = sess.new_channel()?;
131 channel.open_session()?;
132 channel.request_exec("whoami")?;
133 channel.send_eof()?;
134
135 let mut stdout = String::new();
136 channel.stdout().read_to_string(&mut stdout)?;
137
138 eprintln!("whoami -> {}", stdout);
139
140 let res = channel.get_exit_status();
141 eprintln!("exit status: {:?}", res);
142
143 Ok(())
144}