NAME

Net::LibSSH::Channel - SSH exec channel for Net::LibSSH

VERSION

version 0.003

SYNOPSIS

my $ch = $ssh->channel;

$ch->exec('uname -r') or die "exec failed";
my $out = $ch->read;
print "kernel: $out";
print "exit: ", $ch->exit_status, "\n";
$ch->close;

DESCRIPTION

Net::LibSSH::Channel represents an open SSH session channel. Instances are created via "channel" in Net::LibSSH and must not be constructed directly.

A channel keeps its session alive on its own: it holds its own reference to the session object it was opened on, so letting the $ssh variable it came from go out of scope, assigning undef to it, or reassigning it to something else does not invalidate the channel. That guarantee is about the Perl variable, not about the session's connection — it does not protect a channel from $ssh->disconnect; see below.

Calling $ssh->disconnect on the originating session invalidates every channel already opened on it — libssh frees them as part of disconnecting. From that point every channel method but close croaks with "Net::LibSSH::Channel::<method>: session was disconnected", a message distinct from "channel is closed" so a caller can tell its own teardown from libssh's. A channel that was closed with close before its session disconnected keeps reporting "channel is closed" afterwards — whichever happened to the channel first is what it reports. Calling close on a channel invalidated by disconnect is a harmless no-op, not an error, and so is simply dropping the channel (letting it go out of scope, or assigning undef to it) — teardown that has already happened is not a failure.

A channel runs one command per lifetime. After exec completes you can read stdout and stderr independently, then retrieve the exit status. Call close (or let the object go out of scope) to free the underlying libssh channel. close is idempotent; every other channel method croaks once the channel has been closed, with "Net::LibSSH::Channel::<method>: channel is closed".

METHODS

exec($command)

$ch->exec('uname -r') or die "exec failed";

Execute a command on the remote host. Returns 1 on success, 0 on failure. Must be called exactly once per channel.

Croaks if the channel has already been closed (see "close"), or if its session has been disconnected (see "disconnect" in Net::LibSSH).

read([$length [, $is_stderr]])

my $stdout = $ch->read;         # slurp all stdout until EOF
my $chunk  = $ch->read(4096);   # read up to 4096 bytes from stdout
my $stderr = $ch->read(-1, 1);  # slurp all stderr

Read output from the channel. Without arguments (or with -1 length), reads until the remote side closes the stream. With a positive $length, reads at most that many bytes. Pass a true $is_stderr as the second argument to read from stderr instead of stdout.

Note: Do not pass undef as the length — it evaluates to 0 and reads nothing. Use -1 or omit the argument entirely to slurp all output. Nothing is consumed from the channel by a zero-length read, so the data is not lost — a later read call still returns it in full.

Note: read has no way to tell a clean end-of-stream apart from a read error. Both end the same underlying loop and come back as a (possibly empty) string; read never returns undef and never croaks over a read failure itself.

Returns a string (possibly empty). Croaks if the channel has already been closed (see "close"), or if its session has been disconnected (see "disconnect" in Net::LibSSH).

write($data)

my $n = $ch->write("input\n");

Write $data to the channel's standard input. Returns the number of bytes written, or a negative value on error.

Croaks if the channel has already been closed (see "close"), or if its session has been disconnected (see "disconnect" in Net::LibSSH).

send_eof

$ch->send_eof;

Signal end-of-input to the remote command. Call this after all write calls so that commands reading stdin (e.g. cat) know to terminate.

Croaks if the channel has already been closed (see "close"), or if its session has been disconnected (see "disconnect" in Net::LibSSH).

eof

$ch->send_eof;
my $out = $ch->read;
$ch->eof and print "channel closed by remote\n";

Returns true when the remote side has sent EOF on its stdout.

Croaks if the channel has already been closed (see "close"), or if its session has been disconnected (see "disconnect" in Net::LibSSH).

exit_status

my $rc = $ch->exit_status;

Returns the exit status of the executed command. The supported order is to read all output first; called before that, this returns -1 until the remote process has exited.

Measured against libssh 0.10.6: ssh_channel_get_exit_status pumps the session's own packet loop while it waits, so calling exit_status before draining the output still returns the correct exit code there, and does not discard what has not been read yet — a later read still returns it in full. That is behaviour of the libssh build under test, not a portable guarantee; a build that blocks instead of pumping the loop would hang here rather than return -1. Keep reading output before checking exit_status as the supported order regardless.

Croaks if the channel has already been closed (see "close"), or if its session has been disconnected (see "disconnect" in Net::LibSSH). Note that exit_status must be read before close and before $ssh->disconnect, not after either: once the channel is closed, or its session has disconnected, this croaks instead of returning the exit code.

close

$ch->close;

Close the channel and free the underlying libssh resources (send EOF, close, free). Also called automatically when the object is garbage-collected.

close is idempotent — calling it again on an already-closed channel is a no-op, not an error. Every other channel method croaks once the channel is closed, with "Net::LibSSH::Channel::<method>: channel is closed".

close is also a no-op, not an error, on a channel invalidated by $ssh->disconnect — see "disconnect" in Net::LibSSH. It never croaks with "session was disconnected"; that message is reserved for the other methods.

SEE ALSO

Net::LibSSH, Net::LibSSH::SFTP

SUPPORT

Issues

Please report bugs and feature requests on GitHub at https://github.com/Getty/p5-net-libssh/issues.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <getty@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.