NAME
Net::SSH::Any - SSH client module
SYNOPSIS
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);
DESCRIPTION
**************************************************************
*** ***
*** 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.
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.
BACKENDS
The backends (modules that interface with other Perl SSH client modules or external binaries) currently available are as follows:
- Net_OpenSSH
-
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.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.
- Net_SSH2
-
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.
- Ssh_Cmd
-
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.
- Plink_Cmd
-
This backend uses the
plink
utility, part of the PuTTY package.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.
- Sexec_Cmd
-
This backend uses the
sexec
utility that is bundled with the non-free Bitwise SSH client.This backend also establishes a new SSH connection for every remote command run and so it is reliable but slow.
- Sshg3_Cmd
-
This backend uses the
sshg3
utility that is bundled with the non-free Tectia SSH client.This module supports password authentication in a secure manner and it is also quite fast as the Tectia client reuses connections.
DEPENDENCIES
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:
- IO::Pty
-
Used for password authentication with the
Net_OpenSSH
andSsh_Cmd
backends. - Net::OpenSSH
-
Used by the
Net_OpenSSH
backend and also when a non-POSIX shell quoter is required. - Net::SSH2
-
Used by the
Net_SSH2
backend. - Net::SFTP::Foreign
-
Required for SFTP support.
- Win32::SecretFile
-
Used by the
Sshg3_Cmd
backend on Windows.
API
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.
Optional parameters
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 ~/");
Error handling
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;
Shell quoting
By default when calling remote commands, this module tries to mimic perl system
builtin in regard to argument processing.
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.
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.
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.
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).
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:
$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');
Timeouts
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.
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).
Net::SSH::Any methods
These are the methods available from the module:
- $ssh = Net::SSH::Any->new($target, %opts)
-
This method creates a new Net::SSH::Any object representing a SSH connection to the remote machine as described by
$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');
- user => $user_name
-
Login name
- port => $port
-
TCP port number where the remote server is listening.
- password => $password
-
Password for user authentication.
- key_path => $key_path
-
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. - passphrase => $passphrase
-
Passphrase to be used to unlock the private key.
- batch_mode => 1
-
Disable any authentication method requiring user interaction.
- timeout => $seconds
-
Default timeout.
- argument_encoding => $encoding
-
The encoding used for the commands and arguments sent to the remote stream.
- stream_encoding => $encoding
-
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.
- encoding => $encoding
-
This option is equivalent to setting
argument_encoding
andstream_encoding
. - remote_shell => $shell
-
Name of the remote shell. This argument lets the module pick the right shell quoter.
- known_hosts_path => $path
-
Location of the
known_hosts
file where host keys are saved.On Unix/Linux systems defaults to
~/.ssh/known_hosts
, on Windows to%APPDATA%/libnet-ssh-any-perl/known_hosts
. - strict_host_key_checking => $bool
-
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. - remote_*_cmd => $remote_cmd_path
-
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
).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');
- local_*_cmd => $local_cmd_path
-
Similar to
remote_*_cmd
parameters but for local commands.For instance:
$ssh = Net::SSH::Any->new($target, remote_ssh_cmd => '/usr/local/bin/ssh');
- backends => \@preferred_backends
-
List of preferred backends to be tried.
- backend_opts => \%backend_opts
-
Options specific for the backends.
- $ssh->error
-
This method returns the error, if any, from the last method.
- $ssh->system(\%opts, @cmd)
-
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:
- timeout => $seconds
-
If there is not any network traffic over the given number of seconds, the command is aborted. See "Timeouts".
- stdin_data => $data
- stdin_data => \@data
-
The given data is sent as the remote command stdin stream.
- stdout_fh => $fh
-
The remote stdout stream is redirected to the given file handle.
- stdout_file => $filename
-
The remote stdout stream is saved to the given file.
- stdout_discard => $bool
-
The remote stdout stream is discarded.
- stderr_to_stdout => $bool
-
The remote stderr stream is mixed into the stdout stream.
- stderr_fh => $fh
-
The remote stderr stream is redirected to the given file handle.
- stderr_file => $filename
-
The remote stderr stream is saved on the given file.
- stderr_discard => $bool
-
The remote stderr stream is discarded.
- $output = $ssh->capture(\%opts, @cmd)
- @output = $ssh->capture(\%opts, @cmd)
-
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.The set of options accepted by this method is as follows:
- timeout => $seconds
-
Remote command timeout.
- stdin_data => $data
- stdin_data => \@data
-
Data to be sent through the remote command stdin stream.
- stderr_to_stdout => $bool
-
The remote stderr stream is redirected to the stdout stream (and then captured).
- stderr_discard => $bool
-
Remote stderr is discarded.
- stderr_fh => $fh
-
Redirect remote stderr stream to the given file handle.
- stderr_file => $filename
-
Save the remote stderr stream to the given file.
- ($stdout, $stderr) = $ssh->capture2(\%opts, @cmd)
-
Captures both the stdout and stderr streams from the remote command and returns them.
- timeout => $seconds
-
Command is aborted after the given numbers of seconds with no activity elapse.
- stdin_data => $data
- stdin_data => \@data
-
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;
- $pipe = $ssh->pipe(\%opts, @cmd)
-
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.
- $ssh->scp_get(\%opts, @srcs, $target)
-
Copies the given files from the remote host using scp.
The accepted set of options are as follow:
- glob => $bool
-
Allows the remote shell to expand wildcards when selecting the files to download.
- recursive => $bool
-
When this flag is set, the module will descend into directories and retrieve them recursively.
- copy_attr => $bool
-
When this flag is set the attributes of the local files (permissions and timestamps) are copied from the remote ones.
- copy_perm => $bool
- copy_time => $bool
-
Selectively copy the permissions or the timestamps.
- update => $bool
-
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.
- numbered => $bool
-
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 becomefoo(1)
,foo(2)
, etc.;foo.txt
may becomefoo(1).txt
,foo(2).txt
, etc. - overwrite => $bool
-
When a local file of the same name already exist, overwrite it. Set by default.
- $ssh->scp_put(\%opts, @srcs, $target)
-
Copies the set of given files to the remote host.
The accepted options are as follows:
- glob => $bool
-
Allows wildcard expansion when selecting the files to copy.
- recursive => $bool
-
Recursively descend into directories.
- copy_attr => $bool
-
Copy permission and time attributes from the local files.
- follow_links => 0
-
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.
- $data = $ssh->scp_get_content(\%opts, @srcs)
-
Retrieves the contents of some file or files via SCP.
- $ssh->scp_put_content(\%opts, $target, $content)
-
Creates or overwrites the remote file
$target
with the data given in$content
. - $ssh->scp_mkdir(\%opts, $dir)
-
Creates a directory using SCP.
- $sftp = $ssh->sftp(%opts);
-
Returns a new Net::SFTP::Foreign object connected to the remote system or
undef
in case of failure. - %data = $ssh->autodetect(@tests)
-
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.
FAQ
Frequent questions about this module:
- Disabling host key checking
-
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 pointknown_hosts
to/dev/null
or your preferred OS equivalent.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!
- known_hosts file
-
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.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 systemssh
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. - More questions
-
See also the FAQ from the "FAQ" in Net::OpenSSH module as most of the entries there are generic.
SEE ALSO
Net::OpenSSH, Net::SSH2, Net::SSH::Perl.
BUGS AND SUPPORT
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
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.
My wishlist
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.
TODO
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 AND LICENSE
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.