You can modify the script to construct lists of other information too; this script can be a good starting point for auditing tools.
Here's a sample report generated by this script:
|
Example "rush-license-audit.txt"
This is the output generated by the submit-license-audit.pl script. |
*** RUSH LICENSE AUDIT ***
Hostname Licenses: Valid: Version:
---------------------- ---------------------- ---------------------- ----------------------
zoar 30 09/09/2013-permanent 102-103
tahoe 30 09/09/2013-permanent 102-103
tower 30 09/09/2013-permanent 102-103
eagle 30 09/09/2013-permanent 102-103
meade 30 09/09/2013-permanent 102-103
superior 30 09/09/2013-permanent 102-103
snow 30 09/09/2013-permanent 102-103
huron 30 09/09/2013-permanent 102-103
vista 30 09/09/2013-permanent 102-103
spirit 30 09/09/2013-permanent 102-103
ozark 30 09/09/2013-permanent 102-103
crystal 25 08/15/2013-10/21/2013 102-103
geneva 30 09/09/2013-permanent 102-103
erie 30 09/09/2013-permanent 102-103
|
This can be handy for checking if the license files all match up. On the left is the hostname that was checked, and in the right columns, the data from the license.dat files.
In this case, it's clear to see the license.dat file on host "crystal" is out of date; a smaller 25 host, non-permanent license.
It's assumed the script lives on a file server that all machines involved in the audit can access. Invoke the script with an ABSOLUTE PATH that will resolve on all the machines, e.g.
This script does NOT need to be in the same directory as the usual rush submit scripts, and has no dependency on the .common.pl file.. it's completely standalone.
This script has no GUI; you hand tweak the values at the top of the script to make changes. When you run it, it submits a job that prints the jobid on stdout, and the job generates the audit file, and you can just watch the contents of the "rush-license-audit.txt" file grow in a folder browser monitoring the job's log directory, or by middle-clicking on the Done frames in irush (which should open a text editor to view the file).
This script does not open irush for you, so if you want to monitor the job, you'll need to run irush yourself with the jobid. (or hit 'All Jobs' in irush; the job's title will be "SOFTWARE_AUDIT".)
If you encounter trouble, please contact
with questions or bugs. Feel free to make customizations as you like.
What follows is a brief description of the program, so you can understand how to customize it for your own purposes.
Description of software-audit.pl | |
#!/usr/bin/perl -w # # submit-license-audit.pl -- Audit all the rush license file Valid: dates # # Name Vers Date Comments # Greg Ercolano 1.00 08/06/08 - Initial implementation (submit-audit.pl) # Greg Ercolano 1.10 09/23/13 - Modified to audit rush license.dat files # # (C) Copyright 2008, 2016 Seriss Corporation. All Rights Reserved. # Do not remove this header or copyright notice. You may use and change # this software for internal use, but may not re-distribute it. # If you make changes, please add your name/version/date to the list # above using the format shown. # use strict; $|=1; umask(0); |
Start of program.
Here we enforce perl's strict syntax checking, make sure output is unbuffered ($|=1), and set the umask to zero, to prevent unix permission problems for the files we create. |
### MODIFIABLE VARIABLES: START #### # Use forward slashes in pathnames $G::logdir = "//eagle/net/tmp/logs"; # where to write rush error logs $G::cpus = '+any=10.1@1'; # cpus to be audited ### MODIFIABLE VARIABLES: END #### |
Change these variables to be the appropriate paths on your file server. $G::logdir is the directory that will contain the Rush frame logs. $G::cpus is the rush cpus specification for the machines the job will use. |
$G::audit_file = "$G::logdir/rush-license-audit.txt"; # audit log file @G::search = ( "Licenses:", "Valid:", "Version:" ); |
$G::audit_file sets the pathname of the generated audit file.
Here we set it to be in the job's log directory.
$G::search contains the list of strings to search for in the license.dat file. The value of the lines that match will be appended to the audit log. |
# SUBMIT
if ( ! defined($ARGV[0]) ) {
$G::self = $0; $G::self =~ s%\\%/%g; # \\foo\bar -> //foo/bar
# PREVENT 'NETWORK WORM' STYLE RECURSION
if ( defined($ENV{RUSH_ISDAEMON}) ) { exit(1); }
# CREATE LOGDIR
if ( ! -d $G::logdir ) {
unless(mkdir($G::logdir, 0777)) {
print STDERR "mkdir $G::logdir: $!\n"; exit(1);
}
}
# CREATE EMPTY AUDIT FILE
unless(open(AUDIT, ">$G::audit_file"))
{ print STDERR "ERROR: $G::audit_file: $!\n"; exit(1); }
print AUDIT "*** RUSH LICENSE AUDIT ***\n\n";
# CREATE COLUMN HEADINGS
print AUDIT sprintf("%-22s ", "Hostname");
foreach my $search ( @G::search ) { print AUDIT sprintf("%-22s ", $search); } print AUDIT "\n";
# DOTTED LINE HEADING
print AUDIT sprintf("%-22s ", ("-"x22));
foreach my $search ( @G::search ) { print AUDIT sprintf("%-22s ", ("-"x22)); } print AUDIT "\n";
close(AUDIT);
# SUBMIT JOB
unless( open(SUBMIT, "|rush -submit") )
{ print STDERR "rush -submit: $!\n"; exit(1); }
print SUBMIT <<"EOF";
title RUSH_LICENSE_AUDIT
ram 1
frames 1-1000
logdir $G::logdir
command perl $G::self -render
cpus $G::cpus
imgcommand perl $G::self -imgcommand
EOF
close(SUBMIT);
# Non-zero exit indicates submit failed
if ( $? >> 8 )
{ print STDERR "--- Submit failed\n"; exit(1); } # Submit Failed
exit(0); # Submit OK
}
|
This section submits the job.
It handles creating the log directory if it doesn't exist, clearing out the audit log's previous data by truncating it, and writing new column headers at the top. Later on, when the script runs on the machines, they will append their findings to the audit file in whatever order machines become available.
|
# RETURN THE REQUESTED LICENSE INFO
# $1 - string to search for
#
sub GetLicenseInfo($) {
my $search = $_[0];
my $licfile = "";
if ( -e "c:/rush/etc/license.dat" ) { $licfile = "c:/rush/etc/license.dat"; }
else { $licfile = "/usr/local/rush/etc/license.dat"; }
unless(open(LIC,"<$licfile")) {
print "ERROR: can't open $licfile: $!\n"; exit(1);
}
my $out = "";
while ( | This section defines the function that opens the rush license.dat file and parses out the line to be searched for. |
# RUNNING ON REMOTE MACHINE?
if ( $ARGV[0] eq "-render" ) {
print "--- Working on frame host $ENV{RUSH_HOSTNAME}\n";
# REMOVE THIS HOST FROM JOB (SO IT DOESN'T RUN AGAIN)
system("rush -an $ENV{RUSH_HOSTNAME} -fu");
# BUILD AN AUDIT LINE FOR THIS MACHINE
my $out = sprintf("%-22.22s ", $ENV{RUSH_HOSTNAME});
foreach my $search ( @G::search ) { $out .= sprintf("%-22s ", GetLicenseInfo($search)); } $out .= "\n";
# APPEND LINE TO AUDIT FILE WITH SINGLE "ATOMIC WRITE"
print "Appending to ${G::audit_file}: $out";
unless(open(AUDIT, ">>$G::audit_file"))
{ print STDERR "ERROR: $G::audit_file: $!\n"; exit(1); }
else
{ syswrite(AUDIT, $out, length($out)); close(AUDIT); }
print "\n--- DONE\n";
exit(0);
}
|
This is the section that runs on each machine.
The first thing it does is add this machine's hostname to the job's 'neverhost' list so that this machine doesn't try to run the script again. (We only want to run once on each machine) Next, the script builds a line of info that will be appended to audit log, and appends it using a single atomic write operation, which should ensure the data doesn't get "intermingled" with data being written concurrently by other machines.
|
# USER MIDDLE CLICKED ON A FRAME IN IRUSH? (IMGCOMMAND)
if ( $ARGV[0] eq "-imgcommand" ) {
my $cmd;
if ( -d "c:/rush/etc" ) {
# WINDOWS
$ENV{PATH} = "c:/program files/windows nt/accessories:$ENV{PATH}";
$G::audit_file =~ s%/%\\%g;
$cmd = "start wordpad $G::audit_file";
} elsif ( -d "/Applications" ) {
# MAC
$cmd = "open $G::audit_file";
} else {
# LINUX
$cmd = "gvim $G::audit_file";
$cmd =~ s%\\%/%g;
}
system($cmd);
exit(0);
}
|
This last section is invoked by irush if someone middle-clicks
on one of the job's frames, and handles opening the audit log
in a GUI text editor, using techniques specific to the different
platforms. (Windows, Mac, Linux..)
This behavior is set up by the 'imgcommand' line in the 'SUBMIT' section of this script. |