Net::SSH::Any - SSH client module
use Net::SSH::Any; my $ssh = Net::SSH::Any->new($host, user => $user, password => $passwd); my @out = $ssh->capture(cat => "/etc/passwd"); my ($out, $err) = $ssh->capture2("ls -l /"); $ssh->system("foo"); my $sftp = $ssh->sftp; # returns Net::SFTP::Foreign object $sftp->put($local_path, $remote_path);
************************************************************** *** *** *** NOTE: This is an early release that may contain bugs. *** *** The API is not stable and may change between releases. *** *** *** *** Also, the module tests are quite aggresive, containing *** *** checks for experimental features, and may fail even if *** *** the module mostly works. *** *** *** **************************************************************
Net::SSH::Any is a SSH client module providing a high level and powerful API.
Net::SSH::Any
It can run remote commands and redirect its output or capture it, and perform file transfers using SCP or SFTP easily.
Net::SSH::Any does not implement the SSH protocol itself. Instead, it has a plugable architecture allowing it to delegate that task to other SSH client modules or external binaries.
The backends (modules that interface with other Perl SSH client modules or external binaries) currently available are as follows:
Uses the perl module Net::OpenSSH which relies itself on the OpenSSH ssh binary to connect to the remote hosts. As it uses the multiplexing feature of OpenSSH, it can run several commands (or other operations) over one single SSH connection and so it is quite fast and reliable.
ssh
Using the OpenSSH client also ensures maximum interoperability and a mature an secure protocol implementation.
If you are going to run your program in a Linux/Unix box with a recent version of the OpenSSH client installed, this is probably your best option. On the other hand, Net::OpenSSH does not support Windows.
See Net::SSH::Any::Backend::Net_OpenSSH.
Uses the perl module Net::SSH2 which is a wrapper for the libssh2 C library, a fast and portable implementation of the client side of the SSH version 2 protocol.
Net::SSH2 is an actively maintained module that works on both Unix/Linux an Windows systems (don't known about VMS). Compiling it may be a hard task, specially on Windows, but PPM packages are available from the Internet.
That was intended to be main backend for Net::SSH::Any when used on Windows. Unfortunately, the current stable version of libssh2 is still somewhat buggy, causing this backend to be unreliable.
See Net::SSH::Any::Backend::Net_SSH2.
This backend uses any binary <c>ssh</c> client available on the box that accepts the same command line arguments as the OpenSSH one. In practice that means SSH clients forked from old versions of OpenSSH as for instance, the one bundled in Solaris and other commercial unixen.
Password authentication is only supported on Linux/UNIX and it requires the additional module IO::Pty. It may work under Cygwin too.
This backend establishes a new SSH connection for every remote command run and so it is quite slow, although reliable.
See Net::SSH::Any::Backend::Ssh_Cmd.
This backend uses the plink utility, part of the PuTTY package.
plink
It supports password authentication, but in a somewhat insecure manner, as passwords are given to putty as a command line argument. Anybody (user or program) logged on the machine would be able to see them.
This backend also establishes a new SSH connection for every remote command run and so it is reliable but slow.
See Net::SSH::Any::Backend::Plink_Cmd.
This backend uses the sexec utility that is bundled with the non-free Bitwise SSH client.
sexec
See Net::SSH::Any::Backend::Sexec_Cmd.
This backend uses the sshg3 utility that is bundled with the non-free Tectia SSH client.
sshg3
This module supports password authentication in a secure manner and it is also quite fast as the Tectia client reuses connections.
See Net::SSH::Any::Backend::Sshg3_Cmd.
Depending on the backend selected and on the feature set used, you may need to install additional Perl modules.
What follows is a summary of the optional modules and when they are required:
Used for password authentication with the Net_OpenSSH and Ssh_Cmd backends.
Net_OpenSSH
Ssh_Cmd
Used by the Net_OpenSSH backend and also when a non-POSIX shell quoter is required.
Used by the Net_SSH2 backend.
Net_SSH2
Required for SFTP support.
Used by the Sshg3_Cmd backend on Windows.
Sshg3_Cmd
The API of Net::SSH::Any is heavily based on that of Net::OpenSSH. Basic usage of both modules is mostly identical and it should be very easy to port scripts between the two.
Almost all methods in this package accept as first argument a reference to a hash containing optional parameters. In example:
$ssh->scp_get({recursive => 1}, $remote_src, $local_target); my @out = $ssh->capture({stderr_to_stdout => 1}, "ls ~/");
The hash reference can be omitted when optional parameters are not required. In example:
$ssh->scp_get($remote_src, $local_target); my @out = $ssh->capture("ls ~/");
Most methods return undef or an empty list to indicate failure. Exceptions to this rule are the constructor, which always returns and object, and those methods able to generate partial results as for instance <c>capture</c> or <c>scp_get_content</c>.
The "error" method can always be used to explicitly check for errors. For instance:
my $out = $ssh->capture($cmd); $ssh->error and die "capture method failed: " . $ssh->error;
By default when calling remote commands, this module tries to mimic perl system builtin in regard to argument processing.
system
When calling some method as <c>capture</c>:
$out = $ssh->capture($cmd)
the given command ($cmd) is first processed by the remote shell who performs interpolation of environment variables, globs expansion, redirections, etc.
$cmd
If more than one argument is passed, as in the following example:
$out = $ssh->capture($cmd, $arg1, $arg2)
The module will escape any shell metacharacter so that, effectively, the remote call is equivalent to executing the remote command without going through a shell (the SSH protocol does not provides a way to just avoid the shell by not calling it).
All the methods that invoke a remote command (system, capture, etc.) accept the option quote_args allowing one to force or disable shell quoting.
quote_args
For instance, spaces in the command path will be correctly handled in the following case:
$ssh->system({quote_args => 1}, "/path with spaces/bin/foo");
Deactivating quoting when passing multiple arguments can also be useful, for instance:
$ssh->system({quote_args => 0}, 'ls', '-l', "/tmp/files_*.dat");
In that case, the argument are joined with spaces interleaved.
When the glob option is set in SCP file transfer methods, an alternative quoting mechanism which leaves file wildcards unquoted is used.
glob
Another way to selectively use quote globing or fully disable quoting for some specific arguments is to pass them as scalar references or double scalar references respectively. In practice, that means prepending them with one or two backslashes. For instance:
# quote the last argument for globing: $ssh->system('ls', '-l', \'/tmp/my files/filed_*dat'); # append a redirection to the remote command $ssh->system('ls', '-lR', \\'>/tmp/ls-lR.txt'); # expand remote shell variables and glob in the same command: $ssh->system('tar', 'czf', \\'$HOME/out.tgz', \'/var/log/server.*.log');
The builtin quoting implementation expects a remote shell compatible with Unix sh as defined by the POSIX standard. The module can also use the shell quoters available from Net::OpenSSH when installed (that currently includes quoters for csh and MS Windows).
sh
csh
The remote_shell option can be used to select which one to use both at construction time or when some remote command in invoked. For instance:
remote_shell
$ssh = Net::SSH::Any->new($host, remote_shell => 'csh'); $ssh->system({remote_shell => 'MSWin'}, dir => $directory);
For unsupported shells or systems such as VMS, you will have to perform any quoting yourself:
# for VMS $ssh->system('DIR/SIZE NFOO::USERS:[JSMITH.DOCS]*.TXT;0');
Several of the methods described below support a timeout argument that aborts the remote command when the given time lapses without any data arriving via SSH.
timeout
In order to stop some remote process when it times out, the ideal approach would be to send appropriate signals through the SSH connection , but unfortunately, this is a feature of the standard that most SSH implementations do not support.
As a less than perfect alternative solution, in order to force finishing a remote process on timeout, the module closes its stdio streams. That would deliver a SIGPIPE on the remote process next time it tries to write something.
Most backends are able to detect broken connections due to network problems by other means, as for instance, enabling SO_KEEPALIVE on the TCP socket, or using the protocol internal keep alive (currently, only supported by the Net::OpenSSH backend).
SO_KEEPALIVE
These are the methods available from the module:
This method creates a new Net::SSH::Any object representing a SSH connection to the remote machine as described by $target.
$target
$target has to follow the pattern <c>user:password@hostname:port</c> where all parts but hostname are optional. For instance, the following constructor calls are all equivalent:
Net::SSH::Any->new('hberlioz:f#nta$71k6@harpe.cnsmdp.fr:22'); Net::SSH::Any->new('hberlioz@harpe.cnsmdp.fr', password => 'f#nta$71k6', port => 22); Net::SSH::Any->new('harpe.cnsmdp.fr', user => 'hberlioz', password => 'f#nta$71k6');
Login name
TCP port number where the remote server is listening.
Password for user authentication.
Path to file containing the private key to be used for user authentication.
Some backends (i.e. Net::SSH2), require the public key to be stored in a file of the same name with .pub appended.
.pub
Passphrase to be used to unlock the private key.
Disable any authentication method requiring user interaction.
Default timeout.
The encoding used for the commands and arguments sent to the remote stream.
On operation interchanging data between perl and the remote commands (as opposed to operations redirecting the remote commands output to the file system) the encoding to be used.
This option is equivalent to setting argument_encoding and stream_encoding.
argument_encoding
stream_encoding
Name of the remote shell. This argument lets the module pick the right shell quoter.
Location of the known_hosts file where host keys are saved.
known_hosts
On Unix/Linux systems defaults to ~/.ssh/known_hosts, on Windows to %APPDATA%/libnet-ssh-any-perl/known_hosts.
~/.ssh/known_hosts
%APPDATA%/libnet-ssh-any-perl/known_hosts
When this flag is set, the connection to the remote host will be aborted unless the host key is already stored in the known_hosts file.
Setting this flag to zero, relaxes that condition so that remote keys are accepted unless a different key exists on the known_hosts file.
Some operations (i.e. SCP operations) execute a remote command implicitly. By default the corresponding standard command without any path is invoked (i.e scp).
scp
If any other command is preferred, it can be requested through these set of options. For instance:
$ssh = Net::SSH::Any->new($target, remote_scp_cmd => '/usr/local/bin/scp', remote_tar_cmd => '/usr/local/bin/gtar');
Similar to remote_*_cmd parameters but for local commands.
remote_*_cmd
For instance:
$ssh = Net::SSH::Any->new($target, remote_ssh_cmd => '/usr/local/bin/ssh');
List of preferred backends to be tried.
Options specific for the backends.
This method returns the error, if any, from the last method.
Runs a command on the remote machine redirecting the stdout and stderr streams to STDOUT and STDERR respectively.
Note than STDIN is not forwarded to the remote command.
The set of options accepted by this method is as follows:
If there is not any network traffic over the given number of seconds, the command is aborted. See "Timeouts".
The given data is sent as the remote command stdin stream.
The remote stdout stream is redirected to the given file handle.
The remote stdout stream is saved to the given file.
The remote stdout stream is discarded.
The remote stderr stream is mixed into the stdout stream.
The remote stderr stream is redirected to the given file handle.
The remote stderr stream is saved on the given file.
The remote stderr stream is discarded.
The given command is executed on the remote machine and the output captured and returned.
When called in list context this method returns the output split in lines.
In case of error the partial output is returned. The error method should be used to check that no error happened even when output has been returned.
error
Remote command timeout.
Data to be sent through the remote command stdin stream.
The remote stderr stream is redirected to the stdout stream (and then captured).
Remote stderr is discarded.
Redirect remote stderr stream to the given file handle.
Save the remote stderr stream to the given file.
Captures both the stdout and stderr streams from the remote command and returns them.
Command is aborted after the given numbers of seconds with no activity elapse.
Sends the given data through the stdin stream of the remote process.
Example:
$ssh->system({stdin_data => \@data}, "cat >/tmp/foo") or die "unable to write file: " . $ssh->error;
Returns a bidirectional file handle object (that may be a real operating system file handle or an emulated tied file handle, depending on the used backend), connected to the remote command stdin and stdout streams.
The returned pipe objects provide most of the API of IO::Handle.
Redirects the stderr stream of the remote process into its stdout stream.
Discards the stderr stream of the remote process.
Copies the given files from the remote host using scp.
The accepted set of options are as follow:
Allows the remote shell to expand wildcards when selecting the files to download.
When this flag is set, the module will descend into directories and retrieve them recursively.
When this flag is set the attributes of the local files (permissions and timestamps) are copied from the remote ones.
Selectively copy the permissions or the timestamps.
If the target file already exists locally, it is only copied when the timestamp of the remote version is newer. If the file doesn't exist locally, it is unconditionally copied.
When for some remote file a local file of the same name already exists at its destination, a increasing suffix is added just before any extension.
For instance, foo may become foo(1), foo(2), etc.; foo.txt may become foo(1).txt, foo(2).txt, etc.
foo
foo(1)
foo(2)
foo.txt
foo(1).txt
foo(2).txt
When a local file of the same name already exist, overwrite it. Set by default.
Copies the set of given files to the remote host.
The accepted options are as follows:
Allows wildcard expansion when selecting the files to copy.
Recursively descend into directories.
Copy permission and time attributes from the local files.
Symbolic links are not supported by SCP. By default, when a symbolic link is found, the method just copies the file pointed by the link.
If this flag is unset symbolic links are skipped.
Retrieves the contents of some file or files via SCP.
Allows wildcard expansion on the remote host when selecting the files to transfer.
Recursively descends into directories
Creates or overwrites the remote file $target with the data given in $content.
$content
The permissions for the new remote file. Defaults to 0666.
Sets the atime and mtime properties of the remote file.
Creates a directory using SCP.
Sets the permissions of the remote directories created. Defaults to 0777.
Sets the atime and mtime properties of the remote directories.
Returns a new Net::SFTP::Foreign object connected to the remote system or undef in case of failure.
undef
Calls Net::SSH::Any::Autodetect, which implements tests and heuristics that allow one to discover several properties about the remote machine as for instance its operating system or the user shell.
That module is still highly experimental and the way it is used or the format of the returned data may change in future releases.
Frequent questions about this module:
Query: How can host key checking be completely disabled?
Answer: You don't want to do that, disabling host key checking breaks SSH security model. You will be exposed to man-in-the-middle attacks, and anything transferred over the SSH connection may be captured by a third party, including passwords if you are also using password authentication.
Q: I don't mind about security, can I disable host key checking?
A: You have been warned...
The way to disable host key checking is to unset the strict_host_key_checking flag and point known_hosts to /dev/null or your preferred OS equivalent.
strict_host_key_checking
/dev/null
In example:
my $ssh = Net::SSH::Any->new($host, strict_host_key_checking => 0, known_hosts_path => ($^O =~ /^Win/ ? 'nul' : '/dev/null'));
I am not making that easier on purpose!
Q: How can I manipulate the known_hosts file. I.e, adding and removing entries?
A: If you have a recent version of OpenSSH installed on your machine, the companion utility ssh-keygen(1) provides a relatively easy to use command line interface to such file.
ssh-keygen(1)
Otherwise, you can just add or remove the entries manually using a text editor.
If you are on Linux/Unix and using the default known_hosts file, an easy way to add some host key to it is to just log once manually from the command line using your system ssh command. It will get the key from the remote host and ask you if you want to add the key to the store.
Later versions of Net::SSH2 provide basic support for known_hosts file manipulation in Net::SSH2::KnownHosts.
See also the FAQ from the "FAQ" in Net::OpenSSH module as most of the entries there are generic.
Net::OpenSSH, Net::SSH2, Net::SSH::Perl.
Net::SFTP::Foreign
To report bugs send an email to the address that appear below or use the CPAN bug tracking system at http://rt.cpan.org.
Post questions related to how to use the module in Perlmonks http://perlmoks.org/, you will probably get faster responses than if you address me directly and I visit Perlmonks quite often, so I will see your question anyway.
The source code of this module is hosted at GitHub: http://github.com/salva/p5-Net-SSH-Any.
Commercial support, professional services and custom software development around this module are available through my current company. Drop me an email with a rough description of your requirements and we will get back to you ASAP.
If you like this module and you're feeling generous, take a look at my Amazon Wish List: http://amzn.com/w/1WU1P6IR5QZ42.
Also consider contributing to the OpenSSH project this module builds upon: http://www.openssh.org/donations.html.
Thinks that I would like to add in this module in the future:
Host key checking policies
I.e. strict, tofu, ask, advisory.
Install client software automatically
Add infrastructure to download, maybe compile and install client software from the internet. This will be used to test the module in automating testing environments as CPAN Testers or Travis CI.
Expect like functionality
A subset of Expect adapted to work on top of Net::SSH::Any.
Gateway support
I am still not sure about how viable it would be, but I would like to get something like Net::OpenSSH::Gateway available for Net::SSH::Any.
Move to Moo+Moo::Role or Role::Tiny
The ad-hoc composition model used internally by Net::SSH::Any has several quirks that would be gone using the dynamic inheritance model provided by Role::Tiny, though that would probably be a huge effort.
Copyright (C) 2011-2016 by Salvador Fandiño, <sfandino@yahoo.com>
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.12.4 or, at your option, any later version of Perl 5 you may have available.
To install Net::SSH::Any, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Net::SSH::Any
CPAN shell
perl -MCPAN -e shell install Net::SSH::Any
For more information on module installation, please visit the detailed CPAN module installation guide.