package Net::FullAuto;
### OPEN SOURCE LICENSE - GNU AFFERO PUBLIC LICENSE Version 3.0 #######
#
# Net::FullAuto - Powerful Network Process Automation Software
# Copyright © 2000-2016 Brian M. Kelly
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but **WITHOUT ANY WARRANTY**; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License along with this program. If not, see:
#
#######################################################################
our $VERSION='1.0000106';
use 5.005;
use strict;
BEGIN {
my @ARGS=@ARGV;
my $quiet=0;
my $args='';
foreach (@ARGS) {
if ($_ eq '--password') {
$args.='--password ';
shift @ARGS;
$args.='******** '
if ($ARGS[0] && ((length $ARGS[0]<3) ||
(unpack('a2',$ARGS[0]) ne '--')));
next;
} elsif ($_ eq '--quiet' ||
$_ eq '--version' ||
$_ =~ /^-[a-uw-zA-UW-Z]*[Vv]/ ||
$_ =~ '--cat') {
$quiet=1;
}
$args.="$_ ";
} chop $args;
my $nl=(grep { $_ eq '--cron' } @ARGV)?'':"\n";
print "Command Line -> $0 $args\n" if !$nl;
print "STARTING FullAuto© on ". localtime() . "\n"
if !$quiet && (-1<index $0,'fullauto.pl');
our $toppath='';our $cpu='';
$main::planarg||='';$main::cronarg||='';
if ($main::planarg || $main::cronarg) {
if (-e '/usr/bin/top') {
$toppath='/usr/bin/';
} elsif (-e '/bin/top') {
$toppath='/bin/';
} elsif (-e '/usr/local/bin/top') {
$toppath='/usr/local/bin/';
}
if ($toppath) {
my $top_timeout=60;
eval {
$SIG{ALRM} = sub { die "alarm\n" }; # \n required
alarm($top_timeout);
&Net::FullAuto::FA_Core::acquire_semaphore(1111,
"Top CPU check Timed Out at Line: ".__LINE__);
open(OH,"${toppath}top -b -n2 -d.1|") ||
die "Cannot run ${toppath}top -b -n2 -d.1`: $!\n";
while (my $line=<OH>) {
chomp $line;
$cpu=$line if -1<index $line,"idle";
}
close OH;
&Net::FullAuto::FA_Core::release_semaphore(1111);
alarm(0);
};
if ($@ eq "alarm\n") {
print "\n\n";
&handle_error(
"Time for Top CPU check has Expired.",
'__cleanup__');
}
}
}
}
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(fa_login connect_ssh connect_sftp connect_secure cleanup
connect_ftp connect_telnet connect_shell acquire_fa_lock
release_fa_lock send_email ls_parse fetch);
use Term::Menus 2.54;
use JSON;
use URI;
use IO::Pty;
sub fa_login
{
return &Term::Menus::fa_login(@_);
}
sub connect_ssh
{
package connect_ssh;
return Net::FullAuto::FA_Core::connect_ssh(@_);
}
sub connect_shell
{
package connect_shell;
return Net::FullAuto::FA_Core::connect_shell(@_);
}
sub connect_sftp
{
package connect_sftp;
return Net::FullAuto::FA_Core::connect_sftp(@_);
}
sub connect_secure
{
package connect_secure;
return Net::FullAuto::FA_Core::connect_secure(@_);
}
sub connect_ftp
{
package connect_ftp;
return Net::FullAuto::FA_Core::connect_ftp(@_);
}
sub connect_telnet
{
package connect_telnet;
return Net::FullAuto::FA_Core::connect_telnet(@_);
}
sub cleanup
{
package cleanup;
return Net::FullAuto::FA_Core::cleanup(@_);
}
sub acquire_fa_lock
{
package acquire_fa_lock;
return Net::FullAuto::FA_Core::acquire_fa_lock(@_);
}
sub release_fa_lock
{
package release_fa_lock;
return Net::FullAuto::FA_Core::release_fa_lock(@_);
}
sub send_email
{
package send_email;
return Net::FullAuto::FA_Core::send_email(@_);
}
sub fetch
{
package fetch;
return Net::FullAuto::FA_Core::fetch(@_);
}
sub log
{
package log;
return Net::FullAuto::FA_Core::log(@_);
}
sub ls_parse
{
package ls_parse;
return Net::FullAuto::FA_Core::ls_parse(@_);
}
1;
__END__;
######################## User Documentation ##########################
## To format the following documentation into a more readable format,
## use one of these programs: perldoc; pod2man; pod2html; pod2text.
## For example, to nicely format this documentation for printing, you
## may use pod2man and groff to convert to postscript:
## pod2man FullAuto.pm | groff -man -Tps > FullAuto.ps
=head1 NAME
C<Net::FullAuto> - Fully Automate ANY Workload with *Persistent* SSH/SFTP from One Host
=head1 NOTE TO USERS
Please contact me or my team at the following email addresses -
=over 4
=item
B<Brian.Kelly@fullauto.com> or B<team@fullauto.com>
=back
and let us know of any and all bugs, issues, problems, questions
as well as suggestions for improvements to both the documentation
and module itself. We will make every effort to get back to you quickly.
Update the module from CPAN *often* - as we anticipate adding
documentation and fixing bugs and making improvements often.
Brian Kelly, March 9, 2016
=head1 DISCLAIMER
Beware that this software is provided "as is", and comes with no warranty
of any kind, either express or implied. If you use the contents of this
distribution, you do so at your own risk, and you agree to free the
author(s) of any consequences arising from such use, either intended or
otherwise.
=head1 SHELL SYNOPSIS - simple "Hello World"
=over 4
=item
use Net::FullAuto;
$localhost=connect_shell();
($stdout,$stderr,$exitcode)=$localhost->cmd("echo 'Hello World'");
print $stdout;
=back
=head1 SSH & SFTP COMBINED SYNOPSIS
=over 4
=item
use Net::FullAuto;
my $ip_or_hostname = $ARGV[0] || 'localhost';
my $username = $ARGV[1] || getlogin || getpwuid($<);
my $identity_file = $ARGV[2] || ''; # required unless password or
# or key-based login
my $password = $ARGV[3] || ''; # required unless identity file
# or key-based login
my $remote_host_block={
Label => 'Remote Host',
Hostname => $ip_or_hostname,
Login => $username,
IdentityFile => $identity_file, # can leave out if password or
# or key-based login
Password => $password, # can leave out if identity file
# or key-based login
# password is CLEAR TEXT, which
# is poor security. Consider
# IdentityFile or key-based login
#log => 1,
#debug => 1,
#quiet => 1,
};
my ($remote_host_handle,$error)=('',''); # Define and scope variables
($remote_host_handle,$error)=connect_secure($remote_host_block);
die "Connect_SSH ERROR!: $error\n" if $error;
my ($stdout,$stderr,$exitcode)=('','',''); # Define and scope variables
($stdout,$stderr,$exitcode)=
$remote_host_handle->cmd('hostname'); # Run 'hostname' command in
die $stderr if $stderr; # remote command line environment
print "REMOTE HOSTNAME IS: $stdout\n";
($stdout,$stderr,$exitcode)=
$remote_host_handle->cwd('/'); # Change working directory to the
die $stderr if $stderr; # root of the remote host
($stdout,$stderr,$exitcode)=$remote_host_handle->cmd('pwd');
die $stderr if $stderr;
print "REMOTE HOST CURRENT DIRECTORY VIA SSH IS: $stdout\n";
($stdout,$stderr,$exitcode)=$remote_host_handle->cwd('/');
die $stderr if $stderr;
my @stdout=$remote_host_handle->sftp('pwd');
print "REMOTE HOST CURRENT DIRECTORY VIA SFTP IS: $stdout[1]<==\n";
$remote_host_handle->lcd('~');
@stdout=$remote_host_handle->sftp('!pwd');
print "LOCAL HOST CURRENT DIRECTORY VIA SFTP IS: $stdout[1]<==\n";
#$remote_host_handle->close(); # Use this -OR- cleanup method
cleanup; # Use this routine for faster cleanup
=back
=head1 SSH SYNOPSIS
=over 4
=item
use Net::FullAuto;
my $ip_or_hostname = $ARGV[0] || 'localhost';
my $username = $ARGV[1] || getlogin || getpwuid($<);
my $identity_file = $ARGV[2] || ''; # required unless password or
# or key-based login
my $password = $ARGV[3] || ''; # required unless identity file
# or key-based login
my $remote_host_block={
Label => 'Remote Host',
Hostname => $ip_or_hostname,
Login => $username,
IdentityFile => $identity_file, # can leave out if password or
# or key-based login
Password => $password, # can leave out if identity file
# or key-based login
# password is CLEAR TEXT, which
# is poor security. Consider
# IdentityFile or key-based login
#log => 1,
#debug => 1,
#quiet => 1,
};
my ($remote_host_handle,$error)=('',''); # Define and scope variables
($remote_host_handle,$error)=connect_ssh($remote_host_block);
die "Connect_SSH ERROR!: $error\n" if $error;
my ($stdout,$stderr,$exitcode)=('','',''); # Define and scope variables
($stdout,$stderr,$exitcode)=
$remote_host_handle->cmd('hostname'); # Run 'hostname' command in
die $stderr if $stderr; # remote command line environment
print "REMOTE HOSTNAME IS: $stdout\n";
($stdout,$stderr,$exitcode)=
$remote_host_handle->cwd('/'); # Change working directory to the
die $stderr if $stderr; # root of the remote host
($stdout,$stderr,$exitcode)=$remote_host_handle->cmd('pwd');
die $stderr if $stderr;
print "CURRENT DIRECTORY IS: $stdout\n";
#$remote_host_handle->close(); # Use this -OR- cleanup method
cleanup; # Use this routine for faster cleanup
=back
=head1 SFTP SYNOPSIS
=over 4
=item
use Net::FullAuto;
my $ip_or_hostname = $ARGV[0] || 'localhost';
my $username = $ARGV[1] || getlogin || getpwuid($<);
my $identity_file = $ARGV[2] || ''; # required unless password or
# or key-based login
my $password = $ARGV[3] || ''; # required unless identity file
# or key-based login
my $remote_host_block={
Label => 'Remote Host',
HostName => $ip_or_hostname,
LoginID => $username,
IdentityFile => $identity_file, # can leave out if password or
# or key-based login
Password => $password, # can leave out if identity file
# or key-based login
# password is CLEAR TEXT, which
# is poor security. Consider
# IdentityFile or key-based login
#log => 1,
#debug => 1,
#quiet => 1,
};
my ($remote_host_handle,$error)=connect_sftp($remote_host_block);
die "Connect_SFTP ERROR!: $error\n" if $error;
my ($stdout,$stderr)=('','',''); # Define and scope variables
my @stdout=$remote_host_handle->cmd('pwd');
print "REMOTE DIRECTORY IS: @stdout\n";
($stdout,$stderr)=$remote_host_handle->cwd('/');
die $stderr if $stderr;
@stdout=$remote_host_handle->cmd('pwd');
print "CURRENT DIRECTORY IS: @stdout\n";
#$remote_host_handle->close(); # Use this -OR- cleanup method
cleanup; # Use this routine for faster cleanup
=back
=head1 FullAuto Framework SYNOPSIS
=over 4
The FullAuto Framework utilizes the C<fa> command line utility. Using the C<fa> command instead of including C<Net::FullAuto> in your scripts is recommended for better security when using password authentication with remote hosts/devices. Note that in the B<SSH SYNOPSIS> above, there is a C<password =>>C< 'clear_text_password'> element. The FullAuto Framework offers the ability to store such passwords encrypted, and will decrypt them only when actually submitting them to the remote host/device. Such passwords remain encrypted even when stored in memory.
=back
=head1 DESCRIPTION
C<Net::FullAuto>S< > (aka C<FullAuto>) is a Perl module and workload automation framework that transforms Perl into a true multi-host scripting language. It accomplishes this with multiple B<*PERSISTENT*> SSH and SFTP connections to multiple hosts simultaneously. With FullAuto entire hosts are encapsulated in a single filehandle. Think of each filehandle as an always available SSH client (like PuTTY) and SFTP client (like WinSCP) that is available I<progammatically> to the script.
The importance of B<PERSISTENT> connections when attempting to programmatically control remote hosts I<cannot be over stated>. Essentially, it means that FullAuto can automate B<EVERYTHING>.
To see FullAuto in action, please download and explore the "Self Service Demonstration" at L<http://sourceforge.net/projects/fullauto>. The demo contains an embedded YouTube video (L<https://youtu.be/gRwa1QoOS7M>) explaining and showing the entire automated process of setting up a complex multi-host infrastructure in the Amazon EC2 Cloud. After watching or while watching the video, you can run the demo and standup your own cloud infrastructure in just a few minutes. The Hadoop demo is particularly interesting and timely given the recent explosion of BIG DATA and the need to access it more powerfully.
Imagine a scripting language that can turn an entire network of hosts into a virtual single host? This is precisely what FullAuto does.
FullAuto utilizesS< >C<ssh>S< >andS< >C<sftp>S< >(can also useS< >C<telnet>S< >andS< >C<ftp>, though for security reasons, this is NOT recommended) to bring the command enviroments of any number of remote computers (Operating System of remote computer does not matter), together in one convenient scripting space. With FullAuto, you write code once, on one computer, and have it execute on multiple computers simultaneously, in an interactive dynamic fashion, as if the many computers were truly one.
How is FullAuto different from programs like Chef (http://www.chef.io) and Puppet (http://www.puppetlabs.com) and Ansible (http://www.ansible.com) and Salt (http://www.saltstack.com)? All of which assert the same ability and functionality?
Chef and Puppet and Salt require the use of agents on remote hosts. FullAuto has no such dependency as it is agent-less. It works against any ssh server implementation on any operating system. Ansible claims to be "agent-less" but actually has a dependency on the Python scripting language being available on the remote host, as well as requiring that the OpenSSH daemon on remote nodes be configured to utilize the ControlPersist feature. FullAuto has no such dependency (FullAuto does not even require Perl on the remote nodes), and if any manual terminal program or utility can connect to a device viaS< >C<ssh>S< >orS< >C<sftp>S< >orS< >C<scp>S< >or evenS< >C<telnet>S< >orS< >C<ftp>,S< >FullAuto can connect as well - persistently.
Even more exciting, FullAuto goes beyond these frameworks in its unique ability to PROXY-CHAIN multiple hosts with the same persistent connection capability. This means, without agents or any special configuration, FullAuto can proxy connect through any number of hosts and navigate multiple network segments to get you to the host and data you need - in REAL time! Real time interactive command channels and data feeds are the next "big thing", but till now have been incredibly difficult to setup, maintain and keep secure (not to mention "expensive"). With FullAuto, it is now possible for a single ssh process to proxy out through a firewall to a box in the DMZ, from that host go any distance accross the internet to another ssh host in another organization's DMZ, proxy through that host and through the firewall, and continue navigating proxies until the process arrives at the host, functionality and data it needs. For even additional security, the destination organization can also use FullAuto to host a real time "ssh service api" (similar to "web services" which is all rage now) and allow a distant process controlled and precise access to hosts and data just as is provided with web services - without the headache of "certificates", "https", "tokens", etc. - and with much better performance! (due to the simplicity and direct connect capability of FullAuto's architecture). In spite of all the "hoopla", web services are still predominantly "stateless" due to the architecture of the http protocol. FullAuto is state-FULL, insuring the most direct access to remote host functionality and data imaginable - regardless of application. And because FullAuto proxy connections are so lightweight, proxy hosts in DMZ environments can do double duty as "honey pots" - which themselves can be stood up, fully configured and fully managed automatically by FullAuto. The capabilities are almost limitless. (See the 'proxy' configuration element - below).
FullAuto can be run by a user in a Menu driven, interactive mode (using the C<Term::Menus> module - also written by Brian Kelly), or via UNIX or Linux C<cron> or Windows Scheduler or Cygwin C<cron> in a fully automated (and secure) fashion.
Example: A user needs to pull data from a database, put it in a text file, zip and encrypt it, and then transfer that file to another computer on the other side of the world via the internet - in one step, and in a secure fashion.
Assume FullAuto is installed on computer one, the database is on computer two, and the remote computer in China is computer three. When the user starts the script using C<Net::FullAuto>, FullAuto will connect viaS< >C<ssh>S< >andS< >C<sftp>S< >(simultaneously) to computer two, and viaS< >C<sftp>S< >to computer three. Using a sql command utility on computer two, data can be extracted and piped to a text file on computer two. Then, FullAuto will run the command for aS< >C<zip>S< >utility overS< >C<ssh>S< >on computer two to compress the file. Next (assume the encryption software is on computer one) FullAuto will transfer this file to computer one, where it can be encrypted with licensed encryption software, and then finally, the encrypted file can be transferred to computer three viaS< >C<sftp>. Email and pager software can be used for automated notification as well.
Example: The same process above needs to run at 2:00am unattended.
A script using FullAuto can be run viaS< >C<cron>S< >(or any other scheduler) to perform the same actions above without user involvement.
FullAuto is reliable and fault tolerant. Each individual command run on a remote computer returns to FullAuto STDOUT (output) and STDERR (error messages) and command exit codes. With these features, users and programmers can write code to essentially trap remote errors "locally" and respond with any number of error recovery approaches. Everything from sending an e-mail, to re-running the command, to switching remote computers and much more is available as error handling options. The only limits are the skills and ingenuity of the programmers and administrators using FullAuto. If FullAuto loses a connection to a remote host, automatic attempts will be made to re-connect seemlessly - with errors reported when the configured number of attempts fail.
Using FullAuto is easy. Connecting to a remote host is as easy as:
my $remote_host_block={
Label => 'Remote Host',
Hostname => $ip_or_hostname,
Login => $username,
IdentityFile => $identity_file, # can leave out if password or
# or key-based login
# Password => $password, # can leave out if identity file
# or key-based login
};
$computer_one=connect_ssh($remote_host_block);
Commands also are easy:
($stdout,$stderr,$exitcode)=$computer_one->cmd('ls -l');
And no cleanup is necessary -S< >FullAutoS< >handles this AUTOMATICALLY.
FullAuto is secure. It usesS< >C<ssh>S< >andS< >C<sftp>S< >for communication accross hosts and devices. FullAuto connections can be configured to use password-less key exchange. When FullAuto is used in "framework mode" with the C<fa> executable, passwords can be stored encrypted in the Berkeley DB database.
For added security, and enhanced user functionality, FullAuto can be installed on UNIX and Linux based hosts to useS< >C<setuid>. (Windows/Cygwin does not support "setuid" - so this feature is not available on Windows computers. This is the only Windows FullAuto limitation.) With FullAuto setup to useS< >C<setuid>, users can be configured to run complex distributed processes in a secure fashion without the permissions actually needed by the remote (or even local) resources. This setup can allow users to run FullAuto processes without having access to the passwords controlling remote access, or for that matter, the code running those processes.
=head1 Reasons to Use this Module
You want to do everything you could do with other workload automation frameworks like Chef, Puppet, Anisble and Salt without the cost, overhead and resource requirements of those solutions. You want to go beyond those frameworks and set up real-time ssh proxy-chained interactive command channels and data feeds. You want to do managed file transfers via sftp or insecure ftp without having to impose requirements on owners of remote host servers. You want entire automated workloads encapsulated in a single "instruction set" that often is so tiny, you can easily attach it to an email. You want a solution that is as easy to install as C<install Net::FullAuto>. You want the entire CPAN available for use in your "instruction sets". You want the true strengths of Perl and the Perl Community and features like Perl's unsurpassed regular expression functionality readily available. You want the flexibility of a serial scripting language, and the option to use modern OO programming with Moose. You want a solution that can work equally well on both UNIX/Linux and Windows operating syetems (FullAuto works on Windows within the Cygwin Linux layer for Windows evironment).
FullAuto is the SIMPLEST and most direct path to Full Automation (hence the name). That path is to make full use of trusted connectivity components already in widespread use on billions of devices the world over. SSH and SFTP are literally on every UNIX and Linux host in the world - and are both easily added to MS Windows. SSH and SFTP are used to connect to multiple network devices such as routers and switches. SSH and SFTP are a widely available means to connect to the Mainframe. All we EVER needed, was an automation solution that simply utilized this widespread access architecture already in place - AS IS, without requiring any special features or configuration. That solution is now a reality - and it's name is B<FullAuto>.
And soon - there will be the FullAuto Web Service API that will enable anyone in any programming or scripting language to access and use the full power and functionality of FullAuto without having to know Perl at all.
=head1 CONNECT METHODS
=head2 B<%connection_info> - Hash to pass connection information to the following connect_<type> methods.
=over 4
=item
%connection_info=(
Label => '<label_to_identify>',
Hostname => '<hostname>', # Optional - need Hostname -or- IP Address
IP => '<ip address>',
Login => '<login id>',
Use => '<hostname or ip>, # When both Hostname and IP are listed,
# use the specified first
IdentityFile => '<path to file>', # Optional - RECOMMENDED (most secure)
Password => '<password>', # Optional - *NOT* Recommended
Log => 1 | 0, # Optional - Log output to FullAuto log
Debug => 1 | 0, # Optional - Display debug info in output
Quiet => 1 | 0, # Optional - Suppress output
Timeout => <seconds>, # Optional - Default is 90 seconds. Use to extend
# time allowed to establish a connection
Proxy => <\%proxy_connection_info>, # Optional - use other host as a
# Proxy
);
=back
=head3 Label
=over 4
=item
C<Label =E<gt> E<lt>labelE<gt>,>
This element contains the label to identify the host.
=back
=head3 Hostname
=over 4
=item
C<Hostname =E<gt> E<lt>hostnameE<gt>,>
This element contains the hostname of the host. It can also be encoded with an ip address as no validation is done.
=back
=head3 IP
=over 4
=item
C<IP =E<gt> E<lt>ip addressE<gt>,>
This element contains the ip address of the host. It can also be encoded with a hostname as no validation is done.
=back
=head3 Use
=over 4
=item
C<Use =E<gt> E<lt>hostname|ipE<gt>,>
This element is used when both a hostname and ip address are included in C<%connection_info>. It is used to indicate which to "use" first - hostname or ip address. FullAuto will use try the hostname first, if both hostname and ip address are configured, and C<Use> is not used.
=back
=head3 Password
=over 4
=item
C<Password =E<gt> E<lt>passwordE<gt>,>
This element contains the password to use when logging in. You are stongly advised NOT to use this element, as clear text passwords are VERY insecure! Rather, use keys or identityfiles to authenticate against remote ssh/sftp servers.
=back
=head3 IdentityFile
=over 4
=item
C<IdentityFile =E<gt> E<lt>path to identityfileE<gt>,>
This element contains the path to the identityfile used to login to the remote host. If you are not already authenticating with this approach, you are STRONGLY encouraged to consider doing so. Clear text passwords are notoriously unsafe.
=back
=head3 Log
=over 4
=item
C<Log =E<gt> E<lt>1|0|path_to_logfileE<gt>,>
FullAuto has built in logging, but in order to use it, it must be explicitly turned on. It can be turned on and off in C<%connection_info> using this element. A custom logfile and location can be indicated rather than a '1' which simply turns it on. The default location for FullAuto logs is C</home/E<lt>userE<gt>/.fullauto/logs>. FullAuto does NOT have one big log, but rather creates an entirely new log for each script/instruction set invocation. This is a typical example: C<FA9320d031716h14m13s19.log> The naming convention of the file is as follows.
FA -> identifies this as a FullAuto log file
9320 -> PID (Process ID) of the FullAuto process to which this log belongs
d031716 -> Date of the log: March 17, 2016
h14m13s19 -> h: hour 14 (2pm) m: 13 minutes s: 19 seconds
=back
=begin html
<P CLASS="indented">
The <code>Log</code> element is used to dynamically turn on and off logging:<br><br>Turn on logging: <code>Log =&gt; 1,</code><br><br>Turn off logging: <code>Log =&gt; 0,</code><br><br>Turn on logging with custom name and path location: <code>Log =&gt; &lt;path_to_logfile&gt;,</code>
<P>
=end html
=back
=head3 LogCount
=over 4
=item
C<Log =E<gt> E<lt>numberE<gt>,>
This element indicates how many logs to store. When the number is reached, FullAuto will delete the oldest.
=back
=head3 Debug
=over 4
=item
C<Debug =E<gt> E<lt>1|0E<gt>,>
This element instructs FullAuto to print all debug output to the screen.
=back
=head3 Quiet
=over 4
=item
C<Quiet =E<gt> E<lt>1|0E<gt>,>
This element instructs FullAuto suppress all output except Fatal Errors.
=back
=head3 Timeout
=over 4
=item
C<Timeout =E<gt> E<lt>1|0E<gt>,>
This element changes the default timeout value for any command that has no output. As long as a command has output, there is no timeout. The default timeout value is 90 seconds. It is advised that a stream of continuous output be provided if possible. Examine the options of commands you will be using, and use verbose or debug options if output is ordinarily light. When calling custom scripts - make sure those scripts provide output that comes continuously, or at least within the 90 second timeout.
=back
=head3 Proxy
=over 4
=item
C<Proxy =E<gt> E<lt>\%proxy_connection_infoE<gt>,>
=back
=head2 connect_secure() - connect to remote host via ssh and sftp
=over 4
=item
C<($ssh_host_object,$error) = connect_secure(\%connection_info);>
C<$ssh_host_object = connect_secure(\%connection_info);>
=back
=begin html
<STYLE TYPE="text/css">
<!--
.indented
{
padding-left: 50pt;
padding-right: 50pt;
}
-->
</STYLE>
<P CLASS="indented">
Any connection errors will result in complete termination of
the process.</P>
<P CLASS="indented">
The <CODE>$secure_host_object</CODE> represents both ssh AND sftp connections
together in ONE<br>object.</P>
</P>
<P CLASS="indented">
The important thing to understand, is that there is no other code
needed to connect to remote<br>hosts. <code>Net::FullAuto</code> handles all
connection details, such as dynamic remote-prompt discovery,<br>
AUTOMATICALLY. No need to define <i>or even know</i> what the remote
prompt is. This feature<br>'alone' is a major departure from most
other scriptable remote command and file transfer utilities.</P>
=end html
=head2 connect_ssh() - connect to remote host via ssh
=over 4
=item
C<($ssh_host_object,$error) = connect_ssh(\%connection_info);>
C<$ssh_host_object = connect_ssh(\%connection_info);>
=back
=begin html
<P CLASS="indented">
This method returns an ssh connection <i>only</i> - any attempt to
use file-transfer features with this object<br>will throw an error.
</P><P CLASS="indented">
Use this method if you don't need file-transfer capability in
your process.
</P>
=end html
=head2 connect_sftp() - connect to remote host via sftp
=over 4
=item
C<($sftp_host_object,$error) = connect_sftp(\%connection_info);>
C<$sftp_host_object = connect_sftp(\%connection_info);>
=back
=begin html
<P CLASS="indented">
This method returns an sftp connection <i>only</i> - any attempt to
use remote command-line features with this object<br>will throw
an error.</P><P CLASS="indented">Use this method if you don't need
remote command-line capability in your process.</P>
=end html
=head2 connect_insecure() - connect to remote host via telnet & ftp
=over 4
=item
C<($insecure_host_object,$error) = connect_insecure(\%connection_info);>
=back
=begin html
<P CLASS="indented">
All Connect Methods return a <i>host object</i> if connection
is successful, or error message(s)<br>
in the error variable if the method is requested to return a list.
Otherwise, if the method is<br>requested to only return a scalar:
</P>
=end html
=over 4
=item
C<$insecure_host_object = connect_insecure(\%connection_info);>
=back
=begin html
<P CLASS="indented">
Any connection errors will result in complete termination of
the process.</P>
<P CLASS="indented">
The <CODE>$insecure_host_object</CODE> represents both telnet AND ftp
connections together in ONE<br>object.
</P>
=end html
=over 4
=item
THIS METHOD IS *NOT* RECOMMENDED for CONNECTING -
use C<connect_secure()> whenever possible.
=back
=head2 connect_telnet() - connect to remote host via telnet
=over 4
=item
C<($ssh_host_object,$error) = connect_telnet(\%connection_info);>
C<$ssh_host_object = connect_telnet(\%connection_info);>
=back
=begin html
<P CLASS="indented">
This method returns a telnet connection <i>only</i> - any attempt to
use file-transfer features with this object<br>will throw an error.
</P><P CLASS="indented">
Use this method if you don't need file-transfer capability in
your process.
</P>
=end html
=over 4
=item
THIS METHOD IS *NOT* RECOMMENDED for CONNECTING -
use C<connect_ssh()> whenever possible.
=back
=head2 connect_ftp() - connect to remote host via ftp
=over 4
=item
C<($ftp_host_object,$error) = connect_ftp(\%connection_info);>
C<$ftp_host_object = connect_ftp(\%connection_info);>
=back
=begin html
<P CLASS="indented">
This method returns an ftp connection <i>only</i> - any attempt to
use remote command-line features with this object<br>will throw
an error.</P><P CLASS="indented">Use this method if you don't need
remote command-line capability in your process.</P>
=end html
=over 4
=item
THIS METHOD IS *NOT* RECOMMENDED for CONNECTING -
use C<connect_sftp()> whenever possible.
=back
=head2 connect_shell() - connect to local shell
=over 4
=item
C<($shell_localhost_object,$error) = connect_shell();>
C<($shell_localhost_object,$error) = connect_shell(\%connection_info);>
C<$shell_localhost_object = connect_shell();>
C<$shell_localhost_object = connect_shell(\%connection_info);>
=back
=begin html
<P CLASS="indented">
This method returns a local shell handle. When this connect method is
used, a separate process is forked in memory and a local shell (currently
only BASH is supported) is spawned within it. In this way, you can have
any number of local shell processes running that each emulate a command
line environment precisely as if it were a remote host handle. This is an
extremely useful feature and allows you to run a number of local processes
in their own protected environments in parallel. The one difference of note
between a local process and a remote one, is that the <code>\%connection_info
</code> hash is <i>optional</i>. With <code>connect_shell(\%connection_info)
</code> the only elements of <code>\%connection_info</code> that are
available are <code>debug</code>, <code>quiet</code>, and <code>log</code>.
=end html
=head1 Host Object Elements
A Host Object is in fact an ordinary Perl object in that is contains both elements and methods. The elements contain both one or two process handles, and descriptive metadata about the handle(s).
=head2 _hostlabel
=over 4
=item
C<$connect_secure_object-E<gt>{_hostlabel} = [ 'Label','' ];>
=back
=begin html
<P CLASS="indented">
The <code>_hostlabel</code> element contains the label you assigned in the <code>\%connection_info</code> hash passed to the <code>connect_&lt;type&gt;()</code> method. Each object must have a unique label. If FullAuto detects that you are attempting to create a new object with a label already in use by another object, it will terminate with an error. The <code>_hostlabel</code> element is an array, and you may assign more than one label to an object.<br><br><code>$connect_secure_object-E<gt>{_hostlabel} = [ 'Label','Label Two' ];</code>.<br><br>You can access the primary label at anytime with the following syntax:<br><br><code>$connect_secure_object-&gt;{_hostlabel}-&gt;[0];</code>
</P>
=end html
=head2 _cmd_handle
=over 4
=item
C<$connect_secure_object-E<gt>{_cmd_handle} = Net::Telnet=GLOB(0x8006c330);>
C<$connect_ssh_object-E<gt>{_cmd_handle} = Net::Telnet=GLOB(0x8006c330);>
=back
=begin html
<P CLASS="indented">
The <code>_cmd_handle</code> element contains the process handle GLOB. This is a Net::Telnet handle as the <a href="http://search.cpan.org/~jrogers/Net-Telnet-3.04/lib/Net/Telnet.pm">Net::Telnet</a> module from CPAN is used to actually connect spawn a local shell (bash) process, that is then used to launch SSH and SFTP sessions. Don't let the name "Net::Telnet" confuse you - when <code>connect_secure()</code> and other FullAuto secure connect methods are used, the actual clear text and insecure <i>'telnet'</i> protocal is <b>*NOT*</b> being used! SSH and SFTP are being used instead. Net::Telnet can be used as a lightweight "Expect" and that is precisely how it is used in the internals of Net::FullAuto. As such, all the features and methods of Net::Telnet are available within this handle. There are times when it is very useful to access some of Net::Telnet's methods directly and bypass FullAuto's input and output manipulations. When doing so, you will have to account for the output artifacts that FullAuto handles for you, but there are occasions where this is desirable - especially when front-ending and automating interactive command line programs that prompt the user. Examples of this are provided later in the documentation. So just what does FullAuto provide that Net::Telnet does not? For starters, Net::Telnet requires you to know the prompt of each remote host you want to connect and interact with. This sounds like a simple requirement, but in actual practice, this requirement is a MAJOR headache. The truth is, prompts are very dynamic artifacts that change from host to host, shell to shell, user to user, and can and do change without notice. Prompt changes are one of the most common reasons automated workloads break! FullAuto dynamically discovers the prompt for you on login, eliminating this requirement altogether - and making your job of automating processes significantly easier. FullAuto enables you to access correct output, error output from STDERR, and command exit codes with each command sent. Net::Telnet alone does not provide this kind of advanced functionality. FullAuto automatically handles echo'd prompts and other telnet protocol line noise, relieving the user of having to deal with any of it. Many many users over the years have attempted to use Net::Telnet the way they <b>CAN</b> use FullAuto, without understanding and appreciating Net::Telnet's limitations and the actual knowledge and skill needed to use Net::Telnet successfully. The goal of the FullAuto project was to essentially remove nearly all of Net::Telnet's limitations, and allow users to automate workloads as they would intuitively expect they should be able to - like they would do it manually in PuTTY for instance, but <i>programmatically</i> instead. A user can successfully use FullAuto without needing a deep dive into the documentation, and without a big learning curve - unlike when trying to use Net::Telnet alone. FullAuto also provides process locking - a necessary feature when automating large and complex workloads.<br><br>Net::Telnet methods can be accessed in the following manner:<br><br><code>$connect_secure_object-&gt;{_cmd_handle}-&gt;print();</code>
</P>
=end html
=over 4
=item
C<$connect_sftp_object-E<gt>{_cmd_handle} = Net::Telnet=GLOB(0x8006c330);>
=back
=begin html
<P CLASS="indented">
When connecting via the <code>connect_sftp()</code> method, the resulting <code>_cmd_handle</code> element contains the command environment of the local sftp program only. This environment is very limited, with the command set comprising ls, put, get, cd, lcd, etc. One important feature of note however, is the escape to local command line feature which is accomplished with the exclamation point or 'bang' character. This does work as expected with this handle. For example, to get the hostname of the local host, this will work as expected:<br><br><code>$connect_sftp_object->cmd('!hostname');</code>
</P>
=end html
=head2 _ftp_handle
=over 4
=item
C<$connect_secure_object-E<gt>{_ftp_handle} = Net::Telnet=GLOB(0x8006c330);>
=back
=begin html
<P CLASS="indented">
This element exists only when connecting via the <code>connect_secure()</code> and <code>connect_insecure()</code> methods. It's needed with these methods because the <code>_cmd_handle</code> element contains an ssh or telnet or shell command environment. Otherwise, for the <code>connect_sftp()</code> and <code>connect_ftp()</code> methods, the ftp handle is accessed through the <code>_cmd_handle</code> element. An example of usage is the following:<br><br><code>$connect_secure_object->{_ftp_handle}->cmd('!hostname');</code><br><br>Also available is a Host Object Method called ftpcmd(). It can be used instead:<br><br><code>$connect_secure_object->ftpcmd('!hostname');</code>
<P>
=end html
=head2 _cmd_type
=over 4
=item
C<$connect_secure_object-E<gt>{_cmd_type} = 'type'>;
=back
=begin html
<P CLASS="indented">
This element indicates what type of command connection exists in the connect_object. The possible values are <code>'ssh'</code>, <code>'telnet'</code> and <code>'shell'</code>.
<P>
=end html
=head2 _ftm_type
=over 4
=item
C<$connect_secure_object-E<gt>{_ftm_type} = 'type'>;
=back
=begin html
<P CLASS="indented">
This element indicates what type of file transfer connection (or method) exists in the connect_object. The possible values are <code>'ftp'</code> and <code>'sftp'</code>.
<P>
=end html
=head2 _connect
=over 4
=item
C<$connect_secure_object-E<gt>{_connect} = 'connect_E<lt>typeE<gt>'>;
=back
=begin html
<P CLASS="indented">
This element indicates which <code>connect_&lt;type&gt;()</code> method was used to create the host object.
<P>
=end html
=head2 _work_dirs
=over 4
=item
C<$connect_secure_object-E<gt>{_work_dirs} = \%work_dirs;>
=back
=begin html
<P CLASS="indented">
This element is used heavily by the FullAuto <code>cwd()</code> method. It is listed here for informational purposes, but it is NOT recommended that anyone modify these values directly.
<P>
=end html
=head3 _work_dirs -> _cwd
=over 4
=item
C<$connect_secure_object-E<gt>{_work_dirs}-E<gt>{_cwd} = cwd (current working directory in Unix format)>
=back
=begin html
<P CLASS="indented">
This element stores the current working directory in Unix format.
<P>
=end html
=head3 _work_dirs -> _pre
=over 4
=item
C<$connect_secure_object-E<gt>{_work_dirs}-E<gt>{_pre} = (previous working directory in Unix format)>
=back
=begin html
<P CLASS="indented">
This element stores the previous working directory in Unix format.
<P>
=end html
=head3 _work_dirs -> _tmp
=over 4
=item
C<$connect_secure_object-E<gt>{_work_dirs}-E<gt>{_tmp} = /tmp directory>
=back
=begin html
<P CLASS="indented">
This element stores the /tmp directory in Unix format.
<P>
=end html
=head3 _work_dirs -> _cwd_mswin
=over 4
=item
C<$connect_secure_object-E<gt>{_work_dirs}-E<gt>{_cwd_mswin} = cwd - current working directory>
=back
=begin html
<P CLASS="indented">
This element stores the current working directory in MS Windows format.
<P>
=end html
=head3 _work_dirs -> _pre_mswin
=over 4
=item
C<$connect_secure_object-E<gt>{_work_dirs}-E<gt>{_pre_mswin} = previous working directory>
=back
=begin html
<P CLASS="indented">
This element stores the previous working directory in MS Windows format.
<P>
=end html
=head3 _work_dirs -> _tmp_mswin
=over 4
=item
C<$connect_secure_object-E<gt>{_work_dirs}-E<gt>{_tmp_mswin} = temp directory>
=back
=begin html
<P CLASS="indented">
This element stores the temp directory in MS Windows format.
<P>
=end html
=head2 _hostname
=over 4
=item
C<$connect_secure_object-E<gt>{_hostname} = hostname>
=back
=begin html
<P CLASS="indented">
This element indicates hostname of the remote host encapsulated in
the host object. When <code>connect_shell()</code> is used, the
hostname is the local host.
<P>
=end html
=head2 _ip
=over 4
=item
C<$connect_secure_object-E<gt>{_ip} = ip address>
=back
=begin html
<P CLASS="indented">
This element indicates the ip address of the remote host
encapsulated in the host object. When <code>connect_shell()</code>
is used, the ip address is the local host.
<P>
=end html
=head2 _uname
=over 4
=item
C<$connect_secure_object-E<gt>{_uname} = uname of remote host>
=back
=begin html
<P CLASS="indented">
This element indicates uname of the remote host encapsulated
in the host object. When <code>connect_shell()</code> is used,
the uname is from the local host.
<P>
=end html
=head2 _luname
=over 4
=item
C<$connect_secure_object-E<gt>{_luname} = uname of local host>
=back
=begin html
<P CLASS="indented">
This element indicates uname of the local host encapsulated in
the host object. When <code>connect_shell()</code> is used,
the luname is the same as uname.
<P>
=end html
=head2 _cmd_pid
=over 4
=item
C<$connect_secure_object-E<gt>{_cmd_pid} = process id of forked ssh or telnet program>
=back
=begin html
<P CLASS="indented">
This element indicates the process id of the forked ssh or
telnet program encasulated in the host object. When
<code>connect_shell()</code> is used, the _cmd_pid is the
same as _sh_pid.
<P>
=end html
=head2 _sh_pid
=over 4
=item
C<$connect_secure_object-E<gt>{_sh_pid} = process id of the shell within the ssh or telnet connection>
=back
=begin html
<P CLASS="indented">
This element indicates the process id of the shell within the
ssh or telnet connection encasulated in the host object. When
<code>connect_shell()</code> is used, the _sh_pid is the
same as _cmd_pid.
<P>
=end html
=head2 _shell
=over 4
=item
C<$connect_secure_object-E<gt>{_shell} = remote shell>
=back
=begin html
<P CLASS="indented">
This element indicates which shell is being used within
the ssh or telnet connection encasulated in the host object.
<P>
=end html
=head2 _homedir
=over 4
=item
C<$connect_secure_object-E<gt>{_homedir} = home directory on remote host>
=back
=begin html
<P CLASS="indented">
This element indicates the home directory on the remote host.
<P>
=end html
=head2 _cygdrive
=over 4
=item
C<$connect_secure_object-E<gt>{_cygdrive} = cygdrive value when remote environment is Cygwin>
=back
=begin html
<P CLASS="indented">
This element contains the cygdrive value when remote environment is <a href="http://cygwin.com">Cygwin</a>.
<P>
=end html
=head2 _cygdrive_regex
=over 4
=item
C<$connect_secure_object-E<gt>{_cygdrive_regex} = regular expression to test for Cygwin paths>
=back
=begin html
<P CLASS="indented">
This element contains a regular expression to test output for Cygwin style path construction.
<P>
=end html
=head1 Host Object Methods
=head2 cmd() - run ssh, telnet or local shell command line commands on the targeted (remote or local) host
=over 4
=item
C<($cmd_output,$error,$exitcode) = $connect_secure_object-E<gt>cmd('<commandE<gt>');>
=back
=begin html
<P CLASS="indented">
There is a <code>cmd</code> method available with every connect_object.
For all objects that contain both remote command-line and file-transfer
connections, the <code>cmd</code> method gives access ONLY to the
remote command-line feature. To access the ftp cmd options, use the
following syntax:
</P>
=end html
=over 4
=item
C<($ftp_cmd_output,$error) = $connect_secure_object-E<gt>{_ftp_handle}-E<gt>cmd('<ftp commandE<gt>');>
=back
=begin html
<P CLASS="indented">
For all objects that contain only an sftp or ftp
connection, the <code>cmd</code> method gives access ONLY to the
sftp and ftp command-line feature<br><br><code>($sftp_cmd_output,$error,$exitcode) = $connect_sftp_object->cmd('&lt;ftp command&gt;')</code>.
</P>
=end html
=over 4
=item
=================================================================
=back
=begin html
<P CLASS="indented">
The <b>cmd()</b> method is truly the "centerpiece" of FullAuto. This is the one method you will use at least 80% of the time, or more. It is as close to a full "command environment" encapsulated in one handle as could be imagined. Literally, just about anything you could do manually with a shell terminal or program like PuTTY, you can do just as easily with this method. The most important attribute of this method, and of FullAuto itself, is its use of a <b>*PERSISTENT*</b> connection to the remote host. Because of the successful implementation of this approach, STATE is persisted among invocations of this method throughout the life cycle of the "instruction set". In simpler terms, if you change a directory IT STAYS CHANGED. If you add or modify an environment variable, IT STAYS MODIFIED for the next call of the <code>cmd()</code> method. If you do a <code>su</code> or <code>sudo su</code>, the session will remain persistent until you exit. (One caveat - <code>su</code> usage is the one time you will have to account for the prompt and set it yourself). It is this single attribute (persistent connection) that suddenly makes workload automation <b>EASY</b>.<br><br>NOTE: While this does work:<br><br><code>($ssh_cmd_output,$error,$exitcode) = $connect_secure_object->cmd('cd /etc')</code><br><br>It is better to use the FullAuto <code>cwd()</code> method for all file system navigation. This is because it will keep track of history for both command and (s)ftp environments, and keep both environments synchronized.<br><br><code>($ssh_cmd_output,$error,$exitcode) = $connect_secure_object->cwd('/etc')</code>
</P>
=end html
The B<cmd()> method has two other optional arguments
=head3 timeout
=begin html
<P CLASS="indented">
The default timeout value for the <code>cmd()</code> method is 90 seconds. You can change this
by specifiying a timeout value parameter in seconds:<br><br>
The timeout setting is important only with long running commands that do not produce output. As long as a command produces output, the timeout value will not come into play. The command can run literally forever - as long as there is continuous output. It is advised that if you have any control over the output of the command, to enable a sufficient amount of output to avoid having to use the timeout argument. If the command has a "verbose" option, consider activating it. The tradeoff is that supplying output rather than a timeout value increases reliability, and allows the <code>cmd('&lt;command&gt;')</code> to end whenever it needs to - regardless of how long it takes. However, output is "expensive" and to get the quickest return time, using a timeout might produce faster results. But know that you are intentionally choosing speed over reliability, and speed always carries an increased risk.<br><br>
<code>($cmd_output,$error,$exitcode) = $connect_secure_object->cmd('&lt;command&gt;',&lt;seconds&gt;)</code>
</P>
=end html
=head3 __display__
=begin html
<P CLASS="indented">
This parameter turns on sending all STDOUT to the screen in real time as the <code>&lt;command&gt;</code> runs. Without setting this, all STDOUT is sent only to the <code>$cmd_output</code> variable (when set). <code>'__display__'</code> is not position dependent after the <code>&lt;command&gt;</code> parameter (which needs to be the first parameter.) It can appear before any timeout value, or after. <code>'__display__'</code> is a very useful feature for debugging, as well as for processes that human eyes will be anxiously watching closely. Output is "comforting", heals "blank screen anxiety" and allows stakeholders to relax and know that things are working. However, printing output to the screen has costs and slows down processing - significantly. So unless you really need to see output, it's best not to set this.<br><br>
<code>($cmd_output,$error,$exitcode) = $connect_secure_object->cmd('&lt;command&gt;','__display__')</code>
</P>
=end html
=head2 cmd_raw() - run ssh or telnet or local shell command without input validation and output parsing.
=over 4
=item
C<$cmd_output = cmd_raw($connect_secure_object,'<commandE<gt>');>
=back
=begin html
<P CLASS="indented">
There are occasions where a command simply has too many special symbols, quotes, escapes, etc, that no amount of manipulation can get it through FullAuto's input validation correctly. In these cases, sending it through the <cmd_raw()> method and bypassing all of FullAuto's special handling logic, can occasionally produce the desired result. Usually this will work when there is no output, or the output can be discarded. For the most relaible and robust processing, always try to use <code>cmd()</code> as much as possible, savng <cmd_raw()> as a method of last resort. Example of actual command that only works through <code>cmd_raw()</code>:<br><br><code>cmd_raw($connect_secure_object,"sed -i 's/\\(^Session$\\\)/ \\1/' $file_to_modify");</code>
</P>
=end html
=head2 sftpcmd() - run sftp commands on the targeted (remote or local) host
=begin html
<P CLASS="indented">
This method is useful when Host Object contains both a ssh (or telnet) and (s)ftp connection.<br><br>
<code>($sftp_cmd_output,$error) = $connect_secure_object->sftpcmd('&lt;sftp command&gt;')</code><br><br>
Uses same <code>timeout</code> and <code>__display__</code> parameters as the <code>cmd()</code> method.
</P>
=end html
=head2 sftp() - run sftp commands on the targeted (remote or local) host
=begin html
<P CLASS="indented">
Same as sftpcmd above, but a little shorter (and less descriptive) method name.<br><br>
<code>($sftp_cmd_output,$error) = $connect_secure_object->sftp('&lt;sftp command&gt;')</code><br><br>
Uses same <code>timeout</code> and <code>__display__</code> parameters as the <code>cmd()</code> method.
</P>
=end html
=head2 ftpcmd() - run ftp commands on the targeted (remote or local) host
=begin html
<P CLASS="indented">
Same as sftpcmd above, but for ftp.<br><br>
<code>($ftp_cmd_output,$error) = $connect_secure_object->ftpcmd('&lt;ftp command&gt;')</code><br><br>
Uses same <code>timeout</code> and <code>__display__</code> parameters as the <code>cmd()</code> method.
</P>
=end html
=head2 ftp() - run ftp commands on the targeted (remote or local) host
=begin html
<P CLASS="indented">
Same as ftpcmd above, but a little shorter (and less descriptive) method name.<br><br>
<code>($ftp_cmd_output,$error) = $connect_secure_object->ftp('&lt;ftp command&gt;')</code><br><br>
Uses same <code>timeout</code> and <code>__display__</code> parameters as the <code>cmd()</code> method.
</P>
=end html
=head2 cwd() - change working directory for both command (ssh or telnet) and (s)ftp connections simultaneously
=over 4
=item
C<($sftp_cmd_output,$error) = $connect_secure_object-E<gt>cwd('<pathE<gt>');>
C<($sftp_cmd_output,$error) = $connect_secure_object-E<gt>cwd('-');>
C<($sftp_cmd_output,$error) = $connect_secure_object-E<gt>cwd('~');>
C<($sftp_cmd_output,$error) = $connect_secure_object-E<gt>cwd('../..');>
=back
=begin html
<P CLASS="indented">
Unlike any other workload automation framework the author of FullAuto is aware of, this one feature is truly unique to FullAuto. One of the biggest problems there is when a connection is not persistent, is maintaining "state" between commands. When the connection is not persistent, the environment must be updated along with each command sent. This is huge burden on developers, is resource intensive, and makes workload automation extraordinarly complex and fragile. This is precisely why most workload automation software like 'Chef', 'Puppet', 'Salt' and others are Client-Server architecture - requiring agents on all remote hosts/nodes. 'Ansible' is dependent on the "ControlPersist" feature of OpenSSH. The problem with that, is not all SSH servers are OpenSSH, or a recent version of OpenSSH. FullAuto has NO such dependency and will work with ANY SSH server or version of SSH server known to the author. Also, (s)ftp servers <code>cwd</code> and <code>lcd</code> commands do not support common Unix/Linux shell navigation syntax such as '<code>~</code>' for one button access to the user's home directory. But when using the <code>cwd()</code> method supplied with FullAuto, this syntax is fully supported for both the command and (s)ftp environments. The importance of this becomes apparent when you start coding up large and complex instruction sets. The ability to use one single method to change the path location in both environments simultaneously, and to navigate PRECISELY as you would as if you were using a manual terminal like PuTTY, or within any Unix/Linux shell environment, makes it easy for ANYONE who works with these tools regularly to use FullAuto successfully without needing advanced programming language skills or any significant learning curve.
<br><br><code>($cmd_output,$error,$exitcode) = $connect_secure_object->cwd('src')</code><br><code>($cmd_output,$error,$exitcode) = $connect_secure_object->cmd('make install','__display__')</code><br><code>($cmd_output,$error,$exitcode) = $connect_secure_object->cwd('-')</code></P>
=end html
=head2 lcd()
=over 4
=item
C<$connect_secure_object-E<gt>lcd('E<lt>pathE<gt>')>;
=back
=begin html
<P CLASS="indented">
The <code>lcd()</code> method is a convenience method to perform local change directory on the (s)ftp handle without having to do this:<br><br><code>($cmd_output,$error) = $connect_secure_object->{_ftp_handle}->cmd('lcd path')</code><br><br>Also, it supports Unix navigation syntax like '~' for navigating to the home directory, etc.
<P>
=end html
=head2 put()
=over 4
=item
C<$connect_secure_object-E<gt>put('E<lt>fileE<gt>')>;
=back
=begin html
<P CLASS="indented">
The <code>put()</code> method is a convenience method to perform (s)ftp put on the (s)ftp handle without having to do this:<br><br><code>($cmd_output,$error) = $connect_secure_object->{_ftp_handle}->cmd('put file')</code>
<P>
=end html
=head2 get()
=over 4
=item
C<$connect_secure_object-E<gt>get('E<lt>fileE<gt>')>;
=back
=begin html
<P CLASS="indented">
The <code>get()</code> method is a convenience method to perform (s)ftp get on the (s)ftp handle without having to do this:<br><br><code>($cmd_output,$error) = $connect_secure_object->{_ftp_handle}->cmd('get file')</code>
<P>
=end html
=head2 fetch()
=over 4
=item
C<$output = fetch($connect_secure_object);>;
=back
=begin html
<P CLASS="indented">
The <code>fetch()</code> method is used to retrieve raw output straight from the socket when a command is sent via <a href="http://search.cpan.org/~jrogers/Net-Telnet-3.04/lib/Net/Telnet.pm">Net::Telnet</a>'s <code>print()</code> method.<br><br>The following is typical usage of <code>fetch()</code>. In this example, responses to installation options are sent automatically to an interactive <a href="http://www.mysql.com">MySQL</a> command line utility used to perform a secure install of a MySQL database:
<P>
=end html
=over 4
=item
$connect_secure_object->{_cmd_handle}->print('sudo mysql_secure_installation');
# Using Net::Telnet's print() method
my $prompt=substr($connect_secure_object->{_cmd_handle}->prompt(),1,-1);
# Using Net::Telnet's prompt() method to retrieve shell prompt
while (1) {
my $output=fetch($connect_secure_object);
last if $output=~/$prompt/;
print $output;
if (-1<index $output,'root (enter for none):') {
$connect_secure_object->{_cmd_handle}->print();
next;
} elsif (-1<index $output,'Set root password? [Y/n]') {
$connect_secure_object->{_cmd_handle}->print('n');
next;
} elsif (-1<index $output,'Remove anonymous users? [Y/n]') {
$connect_secure_object->{_cmd_handle}->print('Y');
next;
} elsif (-1<index $output,'Disallow root login remotely? [Y/n]') {
$connect_secure_object->{_cmd_handle}->print('Y');
next;
} elsif (-1<index $output,
'Remove test database and access to it? [Y/n]') {
$connect_secure_object->{_cmd_handle}->print('Y');
next;
} elsif (-1<index $output,'Reload privilege tables now? [Y/n]') {
$connect_secure_object->{_cmd_handle}->print('Y');
next;
}
}
=back
=head2 log()
=over 4
=item
C<log('E<lt>1|0|path_to_logfileE<gt>')>;
FullAuto has built in logging, but in order to use it, it must be explicitly turned on. It can be turned on and off anywhere in the script/instruction set using this method. A custom logfile and location can be indicated rather than a '1' which simply turns it on. The default location for FullAuto logs is C</home/E<lt>userE<gt>/.fullauto/logs>. FullAuto does NOT have one big log, but rather creates an entirely new log for each script/instruction set invocation. This is a typical example: C<FA9320d031716h14m13s19.log> The naming convention of the file is as follows.
FA -> identifies this as a FullAuto log file
9320 -> PID (Process ID) of the FullAuto process for which this log belongs
d031716 -> Date of the log: March 17, 2016
h14m13s19 -> h: hour 14 (2pm) m: 13 minutes s: 19 seconds
=back
=begin html
<P CLASS="indented">
The <code>log()</code> method is used to dynamically turn on and off logging:<br><br>Turn on logging: <code>log(1);</code><br><br>Turn off logging: <code>log(0);</code><br><br>Turn on logging with custom name and path location: <code>log(&lt;path_to_logfile&gt;);</code>
<P>
=end html
=head2 ls_parse()
=over 4
=item
C<($size,$timestamp,$file_or_dir)=ls_parse($line);>;
=back
=begin html
<P CLASS="indented">
The <code>ls_parse()</code> method was created because of the frequent need to derive size, timestand and file and directory names from <code>ls -l</code> output from remote hosts.<br><br>The following is typical output from the <code>ls -l</code> command; followed by an example of how <code>ls_parse()</code> can be used:
<P>
=end html
=over 4
=item
($stdout,$stderr)=$connect_secure_object->cmd('ls -l')
---------------------------------------------------------------------------
total 166
drwxrwxrwx+ 1 KB06606 Domain Users 0 Mar 10 10:26 FullAuto
-rw-r--r-- 1 KB06606-admin Domain Users 53383 Mar 14 08:35 FullAuto.html
-rwxr-xr-x 1 KB06606 Domain Users 47560 Mar 13 18:47 FullAuto.pm
-rwxr-xr-x 1 KB06606-admin Domain Users 46742 Mar 13 12:22 FullAuto.pm.bak
-rw-r--r-- 1 KB06606-admin Domain Users 3 Mar 22 2015 pod2htmd.tmp
-rw-r--r-- 1 KB06606-admin Domain Users 3 Mar 22 2015 pod2htmi.tmp
-rw-r--r-- 1 KB06606-admin Domain Users 1784 Jun 14 2015 test.pl
-rwxrwxrwx 1 KB06606-admin Domain Users 1327 Jul 18 2015 tsftp.pl
---------------------------------------------------------------------------
my ($size,$timestamp,$file_or_dir)=('','','');
foreach my $line (split /\n/, $stdout) {
($size,$timestamp,$file_or_dir)=ls_parse($line);
}
=back
=begin html
<P CLASS="indented">
<P>
=end html
=head1 EXAMPLES
=head1 AUTHOR
Brian M. Kelly <Brian.Kelly@fullauto.com>
=head1 COPYRIGHT
Copyright (C) 2000-2016
by Brian M. Kelly.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Affero General Public License.