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. |