A quick method to retrieve the size of a file:
my $file = 'file.txt';
my $fileSize = -s $file;
print "$file is $fileSize bytes\n";
A quick method to retrieve the size of a file:
my $file = 'file.txt';
my $fileSize = -s $file;
print "$file is $fileSize bytes\n";
I have redone some of my previous backup scripts and consolidated them into a single backup and edit script that use a config file for the devices to backup. This script has several options to support cisco and Bluecoat devices. It has functions for tacacs, non-tacacs ssh and even good old telnet to back up devices.
The device-backup script relies on the perl Expect module for interaction. It performs a show version and a show run on cisco routers and switches (put into the backup file with the name and date stamp as part of the name). For ASA’s it sends a more system:running-config, and a show configuration noprompts for Bluecoats. I will add more comprehensive instructions in the future but wanted to get it posted.
Installation:
Basically, download the gz, tar -zxvf device-backup-v.x.tar.gz, make sure you have the correct perl modules installed. You may want to change the config directory to a different location that is in device-backup.pl. Use edit-devices.pl to create, add, modify and delete devices to be backed up (since the passwords are stored base64 encoded in the devices.conf file).
Note: as of Red Hat 6 you’ll need to make sure telnet is installed (since we try to connect to devices this way as well) or your script will error out and complain something like this:
Can’t call method “log_stdout” on an undefined value at ./device-backup.pl line 142, <DEVICES> line 9.
if so, just run ‘yum install telnet’. Thanks Kevin for catching that!
Now that you have a file with an encrypted password in it…it’s no good if you aren’t able to access it. Here’s how you would go about decrypting the same password.
#!/usr/bin/perl
use Crypt::Blowfish;
my $key = pack("H16", "0123456789ABCDEF");
my $passfile = "pass-store";
my $cipher = new Crypt::Blowfish $key;
my $string;
open (IN, "$passfile");
while (<IN>) {
$string = $_;
}
close IN;
chomp $string;
my $ciphertext = $cipher->decrypt($string);
#take the string and decrypt using blowfishchomp $ciphertext;
print "The decrypted value is $ciphertext from $string\n";
This will reference the file named pass-store and pull the encrypted value out like so…
[root@rain ~]# perl decrypt.pl
The decrypted value is Routine1 from ìì?þæìZ:
One thing that you’ll come across sooner or later is how you go about installing new features (modules) with perl. This is something relatively easy if you know where to start. Let’s say you need some capability to encrypt some value like passwords that are stored plain text on a server. There’s a great module (and a hundred others I’m sure) called Crypt::Blowfish that you can find on www.cpan.org that gives you this capability. If you know the modules name that you want to install (crypt::blowfish), you can do so from a command line with the command:
[root@server lee]# perl -MCPAN -e ‘install Crypt::Blowfish’
where the module you want installed is listed after the install command above. This command will also check for dependencies and ask you if you want to install those as well (and you usually do).
Here’s a quick little script to help with encrypting passwords on a server. If you need to keep passwords on a server, say for scripts to use an account as a reference, why not encrypt them? Or maybe you are required to. Here is one method:
#!/usr/bin/perl
use Crypt::Blowfish;
my $key = pack("H16", "0123456789ABCDEF");
my $passfile = "pass-store";
my $cipher = new Crypt::Blowfish $key;
print "Enter a string to encrypt with Blowfish \n";
chomp(my $string = );
my $ciphertext = $cipher->encrypt($string); #take the string and encrypt using blowfish
chomp $ciphertext;
print "The encrypted value is $ciphertext from $string\n";
open (OUTPUT, ">$passfile");
print OUTPUT "$ciphertext";
close OUTPUT;
This will let you encrypt a value of 8 characters into a file called pass-store. Here is what the output looks like.
[root@rain ~]# perl encrypt.pl
Enter a string to encrypt with Blowfish
Routine1
The encrypted value is ìì?þæìZ: from Routine1
Ever wonder how you know which perl modules are installed on a linux box? Here’s a handy little script that will give you this information. Not only does it show you the module installed, it will also display the version (if available). This one is called checkmod.pl, but you can name it anything you like.
#!/usr/local/bin/perl
#checkmod.pl script
use ExtUtils::Installed;
my $instmod = ExtUtils::Installed->new();
foreach my $module ($instmod->modules()) {
my $version = $instmod->version($module) || "???";
print "$module -- $version\n";
}
running this on the commandline will give you output like the following:
[~]# perl checkmod.pl
Archive::Tar — 1.40
Archive::Zip — 1.26
Authen::Libwrap — 0.21
BSD::Resource — 1.2901
Business::OnlinePayment::AuthorizeNet — 3.20
CGI — 3.42
CPAN — 1.9301
Class::Std — 0.0.9
Class::Std::Utils — 0.0.3
Compress::Raw::Bzip2 — 2.005
Cpanel::Cleanup — 0.4
Cpanel::FastMath — 0.2
Cpanel::POSIX::Tiny — 0.7
Crypt::SSLeay — 0.57
Curses — 1.15
Curses::UI — 0.9605
Cwd — 3.25
DBD::Multiplex — 2.09
DBD::mysql — 4.008
DBI — 1.607
DBIx::MyParsePP — 0.50
Data::Dump — 1.11
Devel::PPPort — 3.14
Digest::MD5 — 2.36
Digest::MD5::File — 0.07
Digest::SHA — 5.47
Email::Abstract — 2.134
Email::Date — 1.103
Email::Date::Format — 1.002
Email::Simple — 2.004
Email::Valid — 0.179
Encode — 2.26
Encode::Detect — 1.01
Expect — 1.21
ExtUtils::CBuilder — 0.24
ExtUtils::MakeMaker — 6.48
ExtUtils::ParseXS — 2.19
FCGI — 0.67
File::Copy::Recursive — 0.36
I use this one all the time to make sure I’m using current versions and to make sure the modules I need are installed.
I was looking around for some scripts to see if other people had made a diskspace check script, there were a few but they all seem to depend on modules that don’t install too well. I wanted one that didn’t require any modules since a few of the systems I work on are a pain to get modules on and it seems like this is simple enough to do without requiring them.
So I made this script to take care of that problem. It’s based off of the df command and grabs the results, does some math and makes a decision to send an email or not based on the threshold levels set. There are 2 notification levels, warning and critical that will send emails. If the free disk space is higher than those 2 levels, it will not send out an email. Remember to set permissions and a cronjob for this script to run like so:
35 10 * * * /root/scripts/diskspace.pl
This would run every day at 10:35am. And permissions…
chmod 755 diskspace.pl
#!/usr/bin/perl -w
# Script to check free diskspace and email notifications. Change the email and alert levels and you should be good to go.
# created by lb
use strict;
# Alert levels Warning and Critical - Below what percent level of free disk space do you want an alert?
my $alert1 = 30; #Warning level free space below 30%
my $alert2 = 10; #Critical level free space below 10%
# Put the email address to notify here
my $email = 'you@foo.com';
my ($size,$used,$avail,$use,$mounted);
my $message;
my @list;
my $sysname = `/bin/uname -n`;
chomp $sysname;
my @df = `/bin/df`;
my $df;
foreach $df (@df) {
if ($df =~ /\/\n/) {
@list = split(/\s+/, $df);
}
else {next;}
}
# Check the usage
my $diskfree = (($list[3]) / ($list[2]+$list[3])) * 100.00;
# Round the number off to 2 decimals
$diskfree = sprintf("%.2f", $diskfree);
# See if free disk space is below any of our levels
if ( ($diskfree < $alert1) && ($diskfree > $alert2) ) {
$message = "Warning Diskspace threshold reached...free space below $alert1% at $diskfree%\n";
&mailer;
}
elsif ( ($diskfree < $alert1) && ($diskfree < $alert2) ) {
$message = "Critical Diskspace threshold reached...free space below $alert2% at $diskfree%\n";
&mailer;
}
else {
$message = "Free diskspace is good at $diskfree%\n";
}
#Output to terminal (comment out if you wish)
print $message;
print "~" x 75, "\n@df","~" x 75,"\n","From system: $sysname\n";
#Subroutine for Mail, notifies on warning and critical levels.
sub mailer {
open(MAIL, "|/usr/sbin/sendmail -t") or die "Cannot open sendmail!: $!";
print MAIL "To: $email\n";
print MAIL "From: $sysname\n";
print MAIL "Subject: $message\n\n";
print MAIL "$message";
print MAIL "~" x 75, "\n@df","~" x 75,"\n","From system: $sysname";
close(MAIL);
}
If all is well the commandline response will look like the following:
[root@rain]# perl diskspace.pl
Free diskspace is good at 97.76%
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
305410304 6505676 283390620 3% /
/dev/sda1 194442 19731 164672 11% /boot
tmpfs 900456 48 900408 1% /dev/shm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
From system: rain
#Modules used
use CGI qw(param);
#You should only need to change the directory to start in and maybe the scriptname (if you changed it).
my $dir = "/var/www/html/blog";
my $script = "diff_files.pl";
my @devices = `ls $dir`;
my $query = param('device');
my $file1 = param('file1');
my $file2 = param('file2');
my $diff;
my @filelist;
print <<END_of_Start;
Content-type: text/html
<HTML>
<HEAD>
<TITLE>Find the differences on files</TITLE>
</HEAD>
<BODY>
END_of_Start
if ($query eq "") {
print"
<p>Select folder where you would like to compare files on</p>\n
<FORM ACTION=\"$script\">
<TABLE><TR><TD>Choose a folder</TD></TR><TR><TD><SELECT NAME=device> ";
foreach $device (@devices) {
chomp $device;
print "<option value=$device>$device</option>";
}
print "</SELECT></td></tr><TR><TD><INPUT TYPE=submit></TD></TR></table></form>";
}
elsif ( ($query =~ /\S+/) && ($file1 eq "") ) {
@filelist = `ls $dir/$query`;
print "<p>Device $query, choose the files to compare</p>
<FORM ACTION=\"$script\">
<TABLE><TR><TD>
<SELECT NAME=file1>";
foreach $filelist (@filelist) {
chomp $filelist;
print "<option value=$filelist>$filelist</option>";
}
print "</SELECT></TD><TD>
<SELECT NAME=file2>";
foreach $filelist (@filelist) {
chomp $filelist;
print "<option value=$filelist>$filelist</option>";
}
print "</SELECT></TD></TR><TR><TD><INPUT TYPE=submit><INPUT TYPE=hidden name=device value=$query></TD></TR></table></form>";
}
elsif ( ($file1 =~ /\S+/) && ($file2 =~ /\S+/) ) {
print "<p>comparison of $file1 and $file2</p>";
$diff = `diff -bys $dir/$query/$file1 $dir/$query/$file2`;
#Clean up results
if ($diff =~ /are identical/) {
$diff = "Files are identical.";
}
print "<TABLE width=750><PRE>$diff</PRE><a href=\"$script\">GO BACK</a></TABLE>";
}
This is a script to compare two files and find the difference or diff on them in a web based format. The script uses perl cgi and outputs a side by side comparison of the 2 files, if they are the same the script will report that. If they are different you will see the first file in the left column and the second file in the right with the changes marked, this is handy for a quick diff on large directories or to allow people to compare files without having shell access.
Here is a simple script that will send a test email using Net::SMTP from somewhere to a recipient.
#!/usr/local/bin/perl
use Net::SMTP;
#Vars
$to_email = 'recipient@foo.com';
$from_email = 'sender@foo.com';
$mail_server = "127.0.0.1";
$smtp = Net::SMTP->new("$mail_server");
$smtp->mail ("$from_email");
$smtp->to("$to_email");
$smtp->data();
$smtp->datasend("From: $from_email\n");
$smtp->datasend("To: $to_email\n");
$smtp->datasend("Subject: test message\n");
$smtp->datasend("\n");
$smtp->datasend("A simple test message\n");
$smtp->dataend();
$smtp->quit;
This is handy as a subroutine in a script that you would want to notify you of some value. In order to use it that way, you would change the test message datasend field to a variable containing some information from another section of your script.
Here’s an example for converting a string to have line breaks after every 3 characters. This would be useful for fixed length data…
$str =~ s/(…)/$1\n/g;
So if you had a string with the value aaabbbcccddd it would look like this…
aaa
bbb
ccc
ddd
The $1 references/matches whatever is in the parenthesis.