That's a strange script, and it is difficult to read/understand. Try e.g. serious indentation, and the proposals given above. For your special question, see here:
PrevHostname='' # preset variable to empty
PrevBackup=0 # preset variable to 0
while read input # read variable "input" from stdin
# input contents: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
# input char count: 01234567890123456789012345
# result in variables:
do Month=${input:0:3} # ABC
Day=${input:4:2} # DE
Hostname=${input:13:12} # NOPQRSTUVWX
This is interesting because under this circumstances the script should not run: in AIX 7.1 the default shell is a ksh88 and as far as i know these substring-functions ${var:offset:length} are only available in ksh93, which resides in /usr/bin/ksh93 , not /usr/bin/ksh . You might want to investigate.
It's a fine line between what you have and using perl to do the date processing. As we don't have the whole script some assumptions need to be made on what you are trying to do with these Julian values.
It appears this script is trying to calculate the age in days of particular past dates. The problem with the solution used in this script is that leap years will cause 1 day errors.
Under AIX I would propose using a perl script that tells you the age (in days) of a date eg:
$ agedays.pl "Jan 20 2016"
268
agedays.pl could be written like this:
#!/bin/perl
use POSIX;
use Time::Local;
my %mon;
@mon{qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/} = 0..11;
my ($mmm, $dd, $yy) = split(/[-\/ ]/, $ARGV[0]);
printf "%.0f", (time() - timelocal(0,0,0,$dd,$mon{$mmm}, $yy) - 0.4999) / (24*60*60);
The script then could forget about Current and just fetch the age of the backup like this:
PrevHostname=''
PrevBackup=0
while read input
do
if [[ ${input:9:1} = ':' ]] then
DateStr="${input:0:3} ${input:4:2} $(date +%Y)"
else
DateStr="${input:0:3} ${input:4:2} 20${input:10:2}"
fi
BackupAge=$(agedays.pl "$DateStr")
...
#!/usr/bin/ksh
#
# mksysb.ksh verifies that current mksysb images are being maintained by the two mksysb (NIM) hosts,
# one in the DC1 and anohter in the DC2. The program reads the available mksysb images
# from both hosts along with the date they were created. Converts the creation time into
# a quasi-julian calendar format for comparision the current date. Any mksysb image less
# than three days old is considered "current". Older images are considered "stale". Any
# system belonging to the Unix Operation team from which a mksysb can not be found is
# considered "missing".
#
# while true; do # end-less loop - can be removed in favor of a cron entry
Month=`date|cut -c5-7` # break current date - "Wed Sep 23 16:33:34 EDT 2015"
Day=`date|cut -c9-10` # into Month(Mmm), Day(##) & Year(##)
Year=`date|cut -c27-28`
Rom2Jul() { case $Month in Feb) Day=$(( $Day+31 ));;
Mar) Day=$(( $Day+59 ));;
Apr) Day=$(( $Day+90 ));;
May) Day=$(( $Day+120 ));;
Jun) Day=$(( $Day+151 ));;
Jul) Day=$(( $Day+181 ));;
Aug) Day=$(( $Day+212 ));;
Sep) Day=$(( $Day+243 ));;
Oct) Day=$(( $Day+273 ));;
Nov) Day=$(( $Day+304 ));;
Dec) Day=$(( $Day+334 ));; esac }
Rom2Jul
Current=$(( $Year*365+$Day-2 )) # current ddddd less 3 days to allow for delayed backups & leap year
Path=/tmp/mksysb # for testing ONLY!
BackupInput=$Path/mksysbChk.input
ContactNIM=/usr/local/admin/bin/remote.pl
$ContactNIM --host=NIM1 --command=/bin/'ls -al /nim/dr/mksysb/\*'|grep -e _dr -e .tgz|cut -c37-90|cut -d" " -f2-8|cut -d_ -f1 > $BackupInput # place DC1 clients into the list
$ContactNIM --host=NIM2 --command=/bin/'ls -al /nim/dr/mksysb/\*'|grep -e _dr -e .tgz|cut -c37-90|cut -d" " -f2-8|cut -d_ -f1 >> $BackupInput # append DC2 clients into the list
BackupMsg=$Path/mksysbChk.msg # setup mail strings
BackupTitle='mksysb Status Report'
BackupAdm='xxxxx@xxxx.com'
if [[ ! -s $BackupInput ]] then BackupMsg='ERROR - unable to communicate with the NIM servers and verify mksysb status - NO notifications sent'
mail -s "$BackupTitle" $BackupAdm < $BackupMsg; exit; fi # connection to NIM servers lost, aborting!!!
BackupOutput=$Path/mksysbChk.output
if [[ -e $BackupOutput ]] then rm $BackupOutput; fi
PrevHostname=''
PrevBackup=0
while read input # eliminate duplicate mksysbChk.files & convert raw dates into yy x 365 + ddd format
do Month=${input:0:3}
Day=${input:4:2}
Hostname=${input:13:12}
Rom2Jul
if [[ ${input:9:1} = ':' ]] then Year=`date|cut -c27-28`; else Year=${input:10:2}; fi
Backup=$(( $Year*365+$Day ))
if [[ $PrevHostname = '' ]] then PrevHostname=$Hostname; PrevBackup=$Backup
else if [[ $PrevHostname != $Hostname ]] then echo $PrevBackup $PrevHostname >> $BackupOutput
PrevHostname=$Hostname; PrevBackup=$Backup
else if (( $Backup > $PrevBackup )) then PrevBackup=$Backup; fi; fi; fi; done < $BackupInput
echo $PrevBackup $PrevHostname >> $BackupOutput # write out final record
if [[ -e $BackupMsg ]] then rm $BackupMsg; fi
SupportedHosts=/tmp/aix.lst # daily extract of the supported hostnames
while read Hostname # match supported hostnames with mksysbChk.files & determine status (current/stale/missing)
do Backup=`grep $Hostname $BackupOutput|cut -c1-5` # actual match
if [[ $Backup == '' ]] then echo "$Hostname\tMissing\tmksysb" >> $BackupMsg
else if [[ $Backup < $Current ]] then echo "$Hostname\tStale\tmksysb" >> $BackupMsg; fi; fi; done < $SupportedHosts
mail -s "$BackupTitle" $BackupAdm < $BackupMsg # for testing ONLY!
This should be OK for AIX - dont have system to test it on sorry.
#!/bin/ksh
#
# mksysb.ksh verifies that current mksysb images are being maintained by the two mksysb (NIM) hosts,
# one in the DC1 and anohter in the DC2. The program reads the available mksysb images
# from both hosts along with the date they were created. Converts the creation time into
# a quasi-julian calendar format for comparision the current date. Any mksysb image less
# than three days old is considered "current". Older images are considered "stale". Any
# system belonging to the Unix Operation team from which a mksysb can not be found is
# considered "missing".
#
# while true; do # end-less loop - can be removed in favor of a cron entry
Path=/tmp/mksysb # for testing ONLY!
BackupInput=$Path/mksysbChk.input
ContactNIM=/usr/local/admin/bin/remote.pl
$ContactNIM --host=NIM1 --command=/bin/'ls -al /nim/dr/mksysb/\*'|grep -e _dr -e .tgz|cut -c37-90|cut -d" " -f2-8|cut -d_ -f1 > $BackupInput # place DC1 clients into the list
$ContactNIM --host=NIM2 --command=/bin/'ls -al /nim/dr/mksysb/\*'|grep -e _dr -e .tgz|cut -c37-90|cut -d" " -f2-8|cut -d_ -f1 >> $BackupInput # append DC2 clients into the list
BackupMsg=$Path/mksysbChk.msg # setup mail strings
BackupTitle='mksysb Status Report'
BackupAdm='xxxxx@xxxx.com'
if [[ ! -s $BackupInput ]]
then
BackupMsg='ERROR - unable to communicate with the NIM servers and verify mksysb status - NO notifications sent'
mail -s "$BackupTitle" $BackupAdm < $BackupMsg
exit
fi # connection to NIM servers lost, aborting!!!
BackupOutput=$Path/mksysbChk.output
if [[ -e $BackupOutput ]]
then
rm $BackupOutput
fi
PrevHostname=''
PrevBackup=1000
while read input
do
if [[ ${input:9:1} = ':' ]]
then
DateStr="${input:0:3} ${input:4:2} $(date +%Y)"
else
DateStr="${input:0:3} ${input:4:2} 20${input:10:2}"
fi
BackupAge=$(agedays.pl "$DateStr")
if [[ $PrevHostname = '' ]]
then
PrevHostname=$Hostname
PrevBackup=$BackupAge
else if [[ $PrevHostname != $Hostname ]]
then
echo $PrevBackup $PrevHostname >> $BackupOutput
PrevHostname=$Hostname
PrevBackup=$BackupAge
else if (( $BackupAge < $PrevBackup ))
then
PrevBackup=$BackupAge
fi
fi
fi
done < $BackupInput
echo $PrevBackup $PrevHostname >> $BackupOutput # write out final record
if [[ -e $BackupMsg ]]
then
rm $BackupMsg
fi
SupportedHosts=/tmp/aix.lst # daily extract of the supported hostnames
while read Hostname # match supported hostnames with mksysbChk.files & determine status (current/stale/missing)
do BackupAge=`grep $Hostname $BackupOutput|tail -1 | cut -d' ' -f 1` # actual match
if [[ $BackupAge == '' ]]
then
echo "$Hostname\tMissing\tmksysb" >> $BackupMsg
else if [[ $BackupAge > 0 ]]
then
echo "$Hostname\tStale\tmksysb" >> $BackupMsg
fi
fi
done < $SupportedHosts
mail -s "$BackupTitle" $BackupAdm < $BackupMsg # for testing ONLY!
Note in your script I doubt the line below would work:
do Backup=`grep $Hostname $BackupOutput|cut -c1-5` # actual match
Firstly the $BackupOutput file would contain multiple entries for the host as it's appended each time and also the cut of the first 5 characters would not fetch the numeric julian days correctly. I've replaced this with tail -1 to get the last (most recent) entry for host and used -f option on cut to fetch the first file (being the age).
I cannot cite the output format of all the NIM-commands from memory, but i think the whole script can be replaced by one NIM-command executed. If you do a mksysb from the NIM server a resource of the type MKSYSB is created and entered into the NIMs database, which can subsequently be queried.
You will have to wait until monday when i return to office for details, but i think it will be possible to replace the whole script with a few select lines of code.
OK, being at the office and sitting in front of an xterm pointing at my NIM server does wonders for that old brain of mine ...
Here it is: you can get a list of all NIM objects of a certain type. In this case you are interested in the resources of type "mksysb". Do yourself a favour and, when you take the mksysb with NIM means, give it a proper name. In my case this means: hostname plus a suffix. Issue:
If you work your NIM-server like me you perhaps have some installation-images as mksysbs which you use to instll new systems (see above, the aix71_04_02 ) and the images of the various installed LPARs you take regularly (the others in the list above). Now filter out all the installation images so that only the systems are left and cycle through them, using the -l command line option of lsnim to see the details:
# lsnim -l system_1_mksysb
system_1_mksysb:
class = resources
type = mksysb
creation_date = Sat Oct 15 21:10:56 2016
source_image = system_1
arch = power
Rstate = ready for use
prev_state = unavailable for use
location = /export/mksysb/sys.mksysb
version = 7
release = 1
mod = 3
oslevel_r = 7100-03
oslevel_s = 7100-03
alloc_count = 0
server = master
For instance, a (quick and dirty) code fragment that lists the systems and the creation date of their respective mksysbs, supposing your naming convention is like mine, would be (remove the comments to actually run it):
lsnim -t mksysb | grep -v '^aix' |\ # filter out install-images
while read MKSYSB junk ; do # read only the mksysb-names
lpar="${MKSYSB%%_mksysb}" # cut off trailing "_mksysb"
cdate=$(lsnim -l $MKSYSB |\ # trim o/p to creation date
sed -n '/creation_date/ s/^.*= //p' \
)
print - "$lpar $cdate" # print results
done
I am aware that this is only the sketch of a solution, but it should be fairly straightforward to implement that into a script.
./agedays.pl
Day '' out of range 1..31 at ./agedays.pl line 10
I am getting this error for the code below
#!//usr/local/bin/perl
use POSIX;
use Time::Local;
my %mon;
@mon{qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/} = 0..11;
my ($mmm, $dd, $yy) = split(/[-\/ ]/, $ARGV[0]);
printf "%.0f", (time() - timelocal(0,0,0,$dd,$mon{$mmm}, $yy) - 0.4999) / (24*60*60);