NAME
Script::Toolbox - Framework for the daily business scripts
SYNOPSIS
use Script::Toolbox qw(:all);
$e = Script::Toolbox->new();
#---------
# Logging
#---------
Log( 'log message' ); # log to STDERR
Log( 'log message', 'STDERR' ); # log to STDERR
Log( 'log message', 'STDOUT' ); # log to STDOUT
Log( 'log message', '/tmp/x' ); # log to /tmp/x
Log( 'log message', new IO::File '/tmp/XXX' ); # log to /tmp/XXX
Script::Toolbox->new(
{ logdir'=>{'mod'=>'=s',
desc'=>'Log directory',
mand'=>1,
default'=>'/var/log'}
});
Log( 'log message' ); # log to /var/log/<scriptName>.log
Log( 'log message','syslog','severity','tag' ); # log via syslogd
#--------------------------
# Formatted tables like:
# print join "\n", @{$t};
#--------------------------
$t = Table( [ '1;2;3','44;55;66','7.77;8.88;9.99' ] );
$t = Table( [ '1|2|3','44|55|66','7.77|8.88|9.99' ], '|');
$t = Table( [ 'This is the title',
[ '--H1--', '--H2--', '--H3--'],
[ '11:11:11', 33.456, 'cc ' ],
[ '12:23:00', 2222222, 3 ],
[ '11:11', 222, 3333333333333333 ]]);
$t = Table({ 'title' => 'Hash example',
'head' => ['Col1', 'Col2', 'Col3'],
'data' => [[ '11:11:11', 33.456, 'cc ' ],
[ '12:23:00', 2222222, 3 ],
[ '11:11', 222, 3333333333333333 ]]});
$t = Table({'title'=>'Hash with automatic column heads (F1,F2,F3)',
'data' =>[{'F1'=>'aaaa','F2'=>'bbb','F3'=>'c'},
{'F1'=>'dd ','F2'=>'ee ','F3'=>'f'}]});
# as OO version
my $T = Script::Toolbox::TableO->new([ '1;2;3','44;55;66','7.77;8.88;9.99' ] );
my @T = $T->asArray();
print $T->asString(); # table rows separated by \n
print $T->asString("\n\n"); # table rows separated by \n\n
#----------------------
# Command line options
#----------------------
$x = {'file'=>{'mod'=>'=s','desc'=>'Description', 'mand'=>1, 'default'=>'/bin/cat'},
'int' =>{'mod'=>'=i','desc'=>'Integer option', 'mand'=>1, 'default'=>'10' },
'flag'=>{ 'desc'=>'Boolean option', 'mand'=>0 },
};
$tb = Script::Toolbox->new( $x );
$file = $tb->{'file'};
$old = $tb->SetOpt('newFile');
#--------------------------
# Automatic usage messages
#--------------------------
Usage(); # print a usage message for all options
# if available print also the POD
Usage('This is additional text for the usage');
#--------------------
# Directory handling
#--------------------
$arrRef = Dir('/tmp' ); # all except . and ..
$arrRef = Dir('/tmp', '.*patt' ); # all matching patt
$arrRef = Dir('/tmp', '!.*patt' ); # all not matching patt
$stat = Stat('/bin'); # like Dir() with stat() for each file
$stat = Stat('/bin','.*grep'); # grep,egrep,fgrep
#---------------
# File handling
#---------------
# READ file
$arrRef = File ('path/to/file'); # read file into array
$arrRef = FileC('path/to/file'); # read file into array, chomp all lines
$arrRef = File ('/bin/ps |'); # read comand STDOUT into array
$arrRef = File ('path/to/file', \&callback ); # filter with callback
$arrRef = FileC('path/to/file', \&callback ); # filter with callback, chomp all lines
# WRITE file
File( '> path/to/file', 'override the old content' );
File( 'path/to/file', 'append this to the file' );
File( 'path/to/file', $arrRef ); # append array elements
File( 'path/to/file', $arrRef, $recSep ); # append array elements
# append key <$fldSep> value <$recSep>
File( 'path/to/file', $hashRef, $recSep, $fieldSep);
File( '| /bin/cat', 'Hello world.\n' );
$fileHandle = TmpFile(); # open new temporary file
$arrRef = TmpFile($fileHandle) # read temp whole file
#---------------------------------------------
# Key maps. Key maps are hashs of hashs like:
# key => key => ... key => value
#---------------------------------------------
# fill key map from CSV file
$keyMap = KeyMap('path/to/file');
$keyMap = KeyMap('path/to/file', $fieldSep);
# write the hash to CSV file
KeyMap('path/to/file', $fieldSep, $hashRef);
#---------------
# Miscelleanous
#---------------
Exit( 1, 'Exit message' ); # exit with returncode 1,
# write exit message via Log()
$fh = Open( '> /tmp/xx' ); # return an IO::File object with
# /tmp/xx opened for write
# die with logfile entry if failed
$fh = Open( '/bin/ps |' ); # return an IO::File object
# die with logfile entry if failed
$rc = System('/bin/ls') # execute a system command and
# report it's output into the
# logfile.
#------------------------+
# Date and time handling |
#------------------------+
$n = Now();
print $n->{'mday'},$n->{'mon'}, $n->{'year'},$n->{'wday'}, $n->{'yday'},
$n->{'isdst'},$n->{'sec'}, $n->{'min'}, $n->{'hour'};
print Now->{'epoch'};
$now = Now({'format'=>'%A, %B %d, %Y'}); # Monday, October 10, 2005
$now = Now({'offset'=>3600}); # now + 1 hour
$diff= Now({'diff'=>time()+86400+3600+60+1}); # time+1d+1h+1min+1sec
print $diff->{'seconds'}; # 90061
print $diff->{'minutes'}; # 1501.016
print $diff->{'hours'}; # 25.01694
print $diff->{'days'}; # 1.042373
print $diff->{'DHMS'}; # '1d 01:01:01'
#----------------
# Menue handling
#----------------
# using Menue to start subroutines
my $mainMenue = [{'header'=>'This is the line on top'},
{'footer'=>'This is the bottom line.'},
{'label'=>'EXIT', jump'=>\&_exit, argv'=>0},
{'label'=>'Edit Hosts', jump'=>\&editHosts, argv'=>$ops},
{'label'=>'Activate Host', jump'=>\&activate, argv'=>$ops},
{'label'=>'Changeable Value','value'=>10},
{'label'=>'Read only Value','value'=>10, 'readOnly'=>1},
];
while( 1 ) { my ($o,$mainMenue) = Menue($mainMenue); }
# or ...
my ($resp, $menue) = Menue([{'label'=>'One'},{'label'=>'Two'},{'label'=>'Three'}]);
print 'Second Option' if( $resp == 2 );
# or with header and footer
my ($resp, $menue) = Menue([{'header'=>'This is the optional head line.'},
{'label' =>'One'},{'label'=>'Two'},{'label'=>'Three'},
{'footer'=>'This is the optional footer line.'}]);
print 'Second Option' if( $resp == 2 );
#----------------
# Menue container
#----------------
my $m = Script::Toolbox::Util::Menues->new({'SubMenue1'=>[{'label'=>'Opt1','label'=>'Opt2'}]});
my $m = Script::Toolbox::Util::Menues->new();
$m->addMenue({'MainMenue'=>[{'label'=>'Opt1','label'=>'Opt2'}]});
$m->addOption('MainMenue', {'label'=>'Opt3', 'jump'=>\&callBack });
$m->addOption('MainMenue', {'label'=>'Sub Menue','jump'=>'SubMenue1'});
$m->addOption('MainMenue', {'label'=>'Edit Value','value'=>10});
$m->setAutoHeader(); # enable AutoHeader for all defined menues
$m->setAutoHeader('MainMenue'); # enable AutoHeader for one menue
$m->delAutoHeader(); # disable AutoHeader for all defined menues
$m->delAutoHeader('MainMenue'); # disable AutoHeader for one menue
$m->setHeader('MainMenue','My new header of main manue'); # override setAutoHeader()
$m->setFooter('MainMenue','------');
my $num = $m->run('MainMenue'); # terminate menue after first selection, return seleted option number
$num = $m->run('MainMenue', 3); # terminate menue after third selection, return last seleted option number
$num = $m->run('MainMenue', 0); # terminate never
my $opt = $m->currNumber('MainMenue'); # number of last seleted option
my $lbl = $m->currLabel ('MainMenue'); # label of last seleted option
my $jmp = $m->currJump ('MainMenue'); # callback address of last seleted option
my $val = $m->currValue ('MainMenue'); # data value of last seleted option
#----------------
# Data Menues
#----------------
# using Menue to display and edit some few data values
my $dataMenue = [{'label'=>'EXIT'},
{'label'=>'Name',value'=>''},
{'label'=>'ZIP', value'=>'01468'},
{'label'=>'City',value'=>'Templeton'} ];
while( 1 ) {
my ($o,$dataMenue) = Menue($dataMenue);
last if( $o == 0 );
}
# or ...
my $dataMenue = [{'label'=>'Name',value'=>''},
{'label'=>'ZIP', value'=>'01468'},
{'label'=>'City',value'=>'Templeton'} ];
$dataMenue = DataMenue($dataMenue)
my $data = DataMenue('aaa bbb ccc');
my $data = DataMenue('aaa bbb ccc',{'header'=>'Top Line', 'footer'=>'Bottom Line'});
ABSTRACT
This module should be a 'swiss army knife' for the daily tasks.
The main goals are command line processing, automatic usage
messages, signal catching (with logging), simple logging,
simple data formatting, simple directory and file processing.
DESCRIPTION
- Dir('/path/to/dir')
-
This function lists the file names in the directory into an array (without '.' and '..'). Return a reference to this array or undef if directory is not readable.
- Dir('/path/to/dir', 'regexp')
-
This function lists the file names in the directory into an array (without '.' and '..'). Skip any file names not matching regexp. Return a reference to this array or undef if the directory is not readable.
- Dir('/path/to/dir', '!regexp')
-
This function lists the file names in the directory into an array (without '.' and '..'). Skip any file names matching regexp. Return a reference to this array or undef if the directory is not readable.
- Exit(1,'The reason for the exit.')
-
Exit the script with return value 1. Write the message to the log-channel via Log().
- $arrRef = File('/path/to/file')
-
This function read the file content into an array. Return a reference to this array or undef if the file is not readable.
- $arrRef = File('/path/to/file', \&callback)
-
Read the file into an array. Afterwards call the callback function with a reference to that array. The return value of File() will be the return value of the callback function. In case the callback function do not return anything, a reference to the input array of the callback function will be returned. The callback function may return one scalar value.
Example: ... sub decrypt($) {...} $f = File('path/to/encrypted', \&decrypt);
- File( '> path/to/file', 'overwrite the old content' )
-
Write the string to the file. Overwrite the old content of the file.
- File( 'path/to/file', 'append this to the file' )
-
Append the string to the file.
- File( 'path/to/file', $arrRef )
-
Append each array element to the end of the file as is (no automatic newline).
- File( 'path/to/file', $arrRef, $recSep )
-
Concatenate each array element with the record separator and append it to the file.
- File( 'path/to/file', $hashRef, $recSep, $fieldSep )
-
Append records like KEY$fieldSepVALUE$recSep to the file. Default record separator is the empty string. Default field separator is ':';
- $arrRef = FileC('/path/to/file')
-
Same as File('/path/to/file') but with chomped the results.
- $arrRef = FileC('/path/to/file', \&callback)
-
Same as File('/path/to/file', \&callback) but with chomped the results.
- KeyMap('path/to/file')
-
Read a CSV file with the structure
key1.1,key1.2,...,value1 key2.1,key2.2,...,value2
into a hash of the same structure. The default field separator is ','.
- KeyMap('path/to/file', $fieldSep)
-
Use $fieldSep as field separator.
- KeyMap('path/to/file', \&callback)
-
Same funtionality as in File().
- KeyMap('path/to/file', $fieldSep, \&callback)
-
Same funtionality as in File(). Use $fieldSep as field separator.
- KeyMap('path/to/file', $fieldSep, $hashRef)
-
Write a hash with the structure
key1.1 => key1.2 => ... => value1 key2.1 => key2.2 => ... => value2
into a file of the same structure. Use $fieldSep as field separator.
- Log('The message', [channel])
-
Add a timestamp and write the log message to the channel. The channel may be 'STDERR' (default), 'STDOUT', /path/to/logfile or an IO::File object. Without a channel and using the command line option -logdir /path/to/log the log file will be created under /path/to/log/<scriptName.log>. ScriptName is the basename of the perl script using Script::Toolbox.pm;
- Now({'format'=><'strftime-format'>, offset'=><+-seconds>})
-
Return the actual date and time. If $format is undef the result is a hash ref. The keys are: sec min hour mday mon year wday yday isdst epoch. Month and year are corrected. Epoch is the time in seconds since 1.1.1970. If $format is not undef it must be a strftime() format string. The result of Now() is then the strftime() formated date string. If defined, offset will be added to the epoch seconds before any format convertion takes place.
- Now({'diff'=><time>}) $diff may be a value in epoch seconds or any string parseable by Time::ParseDate. If Now() is called with a diff argument it returns a hash ref with following keys seconds minutes hours days DHMS. Each corresponding value is the difference between now and the given time value.
-
Example: my $d = Now( time()- 1800 ); print $d->{'seconds'} .'s'; # 1800.0s print $d->{'minutes'} .'min'; # 30.0min print $d->{'hours'} .'h'; # 0.5h print $d->{'days'} .'d'; # 0.02083d print $d->{'DHMS'}; # 0d 00:30:00
- Stat('/path/to/dir', '!regexp')
-
Read the directory like Dir() and make a stat() call for each matching file. Skip '.' '..' and any entry matching regexp. Return a reference to a hash or undef if directory not readable.
- Stat('/path/to/dir', 'regexp')
-
Read the directory like Dir() and make a stat() call for each matching file. Skip '.' '..' and any entry not matching regexp. Return a reference to a hash or undef if directory not readable.
Example: $d = Stat('/bin','echo'); print $d->{'echo'}{'atime'}; print $d->{'echo'}{'blksize'}; print $d->{'echo'}{'blocks'}; print $d->{'echo'}{'ctime'}; print $d->{'echo'}{'dev'}; print $d->{'echo'}{'gid'}; print $d->{'echo'}{'ino'}; print $d->{'echo'}{'mode'}; print $d->{'echo'}{'mtime'}; print $d->{'echo'}{'nlink'}; print $d->{'echo'}{'rdev'}; print $d->{'echo'}{'size'}; print $d->{'echo'}{'uid'};
- System( 'command to execute' )
-
Execute a program in a new shell. The STDOUT / STDERR of the executed program will be logged into the logfile. System() returns 0 if the exit code of the program is not 0 otherwise 1;
- Table($dataRef)
-
Table can be used for formatting simple data structures into equal spaced tables. Table knows the folloing input data structures:
Array of CSV lines. Default separator is ';'
Array of arrays. If the first array element is a SCALAR value, we assume it is the title and the second array element has the column headers. Otherwise default title and headers will be generated.
A hash with the keys 'title', 'head' and 'data'. 'title' points to a SCALAR value, 'head' points to a array of scalars. 'data' points to an array of arrays or an array of hashes.
In case of array of hashes, the column heads will be initialized from the keys of the hash in the first array element. The order of the columns is the order of the sorted keys of the hash in the first array element.
- TableO($dataRef)
-
It's an object oriented version of Table (vers. >= 0.50). A Table-Object has two methods.
- Menue
-
There are two types of menues. Regular menues and data menues. All menues use the madatory key 'label'. A data menue has the mandatory key 'value'.
Optional keys for both types are 'header' and 'footer'. All Entries with these keys will be printed on top resp. below the option lines.
Regular menues may use the optional keys 'jump' and 'argv'. Jump points to a handler subroutine. Argv points to the arguments of the handler subroutine.
- Menues
-
This is an object oriented container for regular menues. Each menue generated by Menues->new() gets a automatic RETURN option with option number zero and must have a unique menue-name.
Menue-Methods:
-
If Autoheader is enabled, an automatic header line will be generated for all menues or only the one selected by <menueName>.
'Menue: <menueName>'
-
Disable AutoHeader for all menues or only the one selected by <menueName>.
-
- DataMenue
-
This is a convenient version to edit values via Menue function. It includes an endless loop and an automatic generated EXIT label and exit handling. The edited values will be returned. Acceptable input are the same array with 'label', 'value' hash or a simple white space separated scalar value. In case of simple scalar input an optional hash with 'header' and/or 'footer' keys may be given as second parameter. An option entry like: {'label'=>'Read Only Example', 'value'=>10, 'readOnly'=>1} causes the value will be displayed only.
SIGNALS
The signals SIGINT, SIGHUP, SIGQUIT and SIGTERM will be catched by Script::Toolbox and logged as 'program aborted by signal SIG$sig.'
EXPORT
None by default. Can export Dir, Exit, File, KeyMap, Log, Now, Open, Table, Usage, System, Stat or :all.
SEE ALSO
IO::File, Fatal, Script::Toolbox::Util, Script::Toolbox::Util::Open, Script::Toolbox::Util::Formatter, Script::Toolbox::Util::Menues, Script::Toolbox::TableO, Time::ParseDate
AUTHOR
Matthias Eckardt, <Matthias.Eckardt@imunixx.de>
COPYRIGHT AND LICENSE
Copyright 2002-2016 by Matthias Eckardt, imunixx GmbH
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.