FPUB File Publication Scripts to Publish from Test Apache instance to a Prod Apache instance
File Locations:
/etc/fpub.allowed
/usr/bin/fpub_scp
/usr/bin/fpub
/etc/fpub.allowed contains:
/var/www/html/testfolder:/var/www/html/prodfolder
/var/www/html/testfolder2:/var/www/html/prodfolder2
/usr/bin/fpub_scp contains:
#!/usr/bin/perl -w
use strict;
my $user = 'webmaster';
my $file = $ARGV[0];
my $target = $ARGV[1];
die "fpub_scp invoked with non-existant or unreadable file: $file" if ! $file or !
-r $file;
die "fpub_scp invoked with no target" if ! $target;
# Array of allowed publishing locations
my @locations = ();
# Read list of allowed publish locations from /etc/fpub.allowed
my $allowed_file = '/etc/fpub.allowed';
if (! -r $allowed_file) {
print "Cannot read list of allowed publish locations: $allowed_filen";
print "fpub cannot run until /etc/fpub.allowed is created.n";
exit 1;
}
# Read the list of allowed locations from the allowed_file. While cruising the
list
# make sure that the paths are directories, and strip trailing slashes. Fail
fatally
# if there are any dicrepencies.
open ALLOW, $allowed_file or die "Error Opening $allowed_file: $!";
while (my $line = <ALLOW>) {
chomp $line;
my $loc = [];
if ($line =~ /([^:]*):(.*)/) {
$loc->[0] = $1;
$loc->[1] = $2;
} else {
$loc->[0] = $line;
}
if (! -d $loc->[0]) {
print "Location specified in $allowed_file is not a directory:n";
print "Location: $locn";
exit 100;
}
# Strip trailing slashes
$loc->[0] =~ s//*$//;
$loc->[1] =~ s//*$//;
# All paths must be abolute
if ($loc->[0] !~ /^// || ($loc->[1] && $loc->[1] !~ /^//)) {
print "All paths in fsup.allowed file must be absolute.n";
exit 130;
}
push @locations, $loc;
}
close ALLOW;
# Make sure that the the file specified is in an allowed publish location
# If the location has an applicable replacement, modify destination
my $allowed = 0;
my $destination = $file;
foreach my $loc (@locations) {
if (substr($file, 0, length($loc->[0])) eq $loc->[0]) {
$allowed = 1;
$destination =~ s/^$loc->[0]/$loc->[1]/ if $loc->[1];
}
}
if (! $allowed) {
print "The file you have specified is not in the allowed locations
list.n";
print "File: $filenn";
print "Listing allowed publish locations:nn";
foreach my $loc (@locations) {
print "$locn";
}
exit 120;
}

# Push the file to the remote location
system("scp $file $target:$destination");
/usr/bin/fpub contains:
#!/usr/bin/perl -w
use strict;
use Cwd qw(abs_path);
use Sys::Syslog qw(:standard :macros);
use File::Spec;
openlog('fpub', 'ndelay', LOG_USER);
# User to run as, system to scp to (should be put in a config file)
my $user = 'webmaster';
my $target = 'webprod';
my $relfile = $ARGV[0];
# Make sure that a file was specified
if (! $relfile) {
print "No file specified for publishing.n";
print "Usage: fpub /file/to.publishn";
print "Also, use "fpub list_allowed" to see allowed publishing
locations.n";
exit 1;
}
# List allowed publish locations if requested by the user
if ($relfile eq 'list_allowed') {
print "Listing allowed publish locations:nn";
open ALLOW, '/etc/fpub.allowed' or die "Could not open allowed locations
file /etc/fpub.allowed: $!";
while (<ALLOW>) {
print $_;
}
close ALLOW;
print "n";
exit 0;
}
# Get the absolute path of the file
my $file = File::Spec->rel2abs($relfile);
print "Publishing file: $filen";
my $username = getpwuid($>);
syslog(LOG_INFO, "fpub ($username) publishing file $file");
my $scpret = system("sudo -u $user fpub_scp $file $target");
if ($scpret == 100) {
syslog(LOG_ERR, "fpub ($username) fpub.allowed error, could not publish
file: $file");
} elsif ($scpret == 120) {
syslog(LOG_WARNING, "fpub ($username) publish disallowed for file: $file");
} elsif ($scpret == 130) {
syslog(LOG_ERR, "fpub ($username) fpub.allowed contains relative paths");
} elsif ($scpret != 0) {
syslog(LOG_ERR, "fpub ($username) unspecified error. File: $file");
}
closelog();
File System Update Daemon for synchronizing files between 2 RHAS 4 Apache Servers
File locations:
/var/log/fsupd.webmaster
/etc/fsupd.conf
/etc/rc.d/init.d/fsupd
/usr/local/bin/fsupd.pl

/usr/local/bin/fsupd.pl contains:
#!/usr/bin/perl
use strict;
use POSIX qw(setsid);
use Getopt::Std qw(getopts);
########## BOOTSTRAP ##########
#
# Read the config file
# Check logging directory
# Check user and demote?
# Start logging
# Daemonize
# Author: Thaddeus Hogan
# Get options
my $opts = {};
getopts('d', $opts);
my $debug = $opts->{'d'};
print "Debug output on.n" if $debug;
# Find the config file using the following list in order
my @cfgPaths = (
'fsupd.conf', # Check working directory
'/etc/fsupd.conf' # Check /etc
);
print "Scanning for config location.n" if $debug;
my $cfgPath = undef;
foreach my $c (@cfgPaths) {
print "Checking for config at: $cn" if $debug;
if (-r $c) {
print "Found config at: $cn" if $debug;
$cfgPath = $c;
last;
}
}
if (! $cfgPath) {
print "fsupd Unable to locate configuration file. Terminating.n";
exit 1;
}
# Config file found, parse
my $scanPaths = {};
my $logdir = '/var/log/fsupd';
my $runas = undef;
my $logfile = 'fsupd.log';
my $pidfile = 'fsupd.pid';
open CONF, $cfgPath;
my @cfg = <CONF>;
close CONF;
my $cfgParseMode = 1; # Parse mode 1 = pre-scandefs, 2 = scandefs
my $cscanPath = {}; # Current scan path
foreach my $line (@cfg) {
if ($cfgParseMode == 1) {
$logdir = $1 if $line =~ /logdirs*=s*(.*)/;
$runas = $1 if $line =~ /runass*=s*(.*)/;
$logfile = $1 if $line =~ /logfiles*=s*(.*)/;
$pidfile = $1 if $line =~ /pidfiles*=s*(.*)/;
$cfgParseMode = 2 if $line =~ /^[/;
}
if ($cfgParseMode == 2) {
if ($line =~ /[([^]]*)]/) {
$scanPaths->{$1} = {};
$cscanPath = $scanPaths->{$1};
}
if ($line =~ /(w+)s*=s*(.+)/) {
$cscanPath->{$1} = $2;
}
}
}
my $logpath = "$logdir/$logfile";
# Print out configuration if debug is set
if ($debug) {
print "Config:n";
print "logdir = $logdirn";
print "logfile = $logfilen";
print "runas = $runasn";
foreach my $scanPath (keys %{ $scanPaths }) {
print "Scan Path: $scanPathn";
foreach my $param (keys %{ $scanPaths->{$scanPath} }) {
print "t$param = $scanPaths->{$scanPath}->{$param}n";
}
}
print "n";
}
# Create logging directory if it does not exist
if (! -d $logdir) {
print "Log directory $logdir does not exist, will attempt to create.n" if
$debug;
if (! mkdir($logdir)) {
print "Could not create logging directory: $logdirn";
print "$!n";
print "Terminating.n";
exit 1;
}
}
# Demote daemon if requested
if ($runas) {
print "Preparing to demote process to user: $runasn" if $debug;
# Make sure user can demote
if ($> != 0) {
print "fsupd not run as root, cannot demote to $runas.n";
print "Terminating.n";
exit 1;
}
# Get UID for named user, make sure it exists
my $runasUID = getpwnam($runas);
print "runasUID = $runasUIDn" if $debug;
if (! $runasUID) {
print "fsupd requested to run as $runas but user does not
exist.n";
exit 1;
}
# Make sure the log directory is owned by the requested user
chown $runasUID, -1, $logdir;
if (-e $logpath) {
chown $runasUID, -1, $logpath;
}
# Demote the process
$> = $runasUID;
print "Process demoted to $runas.n" if $debug;
}
# Start logging
my $logfh = undef;
open $logfh, ">>$logpath";
select((select($logfh), $| = 1)[0]); # Make it hot
# Daemonize
&log("fsupd startup successful, daemonizing");
my $pid = fork;
if ($pid) {
&log("daemon process is $pid");
print "daemon process is $pidn" if $debug;
open PIDF, ">$logdir/$pidfile";
print PIDF $pid;
close PIDF;
exit;
}
open STDOUT, "/dev/null";
open STDERR, "/dev/null";
setsid();
######### BUILD MONITOR CHAIN ##########
# Run through the scan paths and construct the monitor chain
# This will be used in a state pump (shift, process, push)
my @monitors = ();
foreach my $scanPath (keys %{ $scanPaths }) {
# Sanity check
if (! -d $scanPath) {
&log("scan path not directory, excluding: $scanPath");
next;
}
if (! -r $scanPath) {
my $uname = getpwnam($>);
&log("scan path not readable by $uname($>), excluding: $scanPath");
next;
}
# Create monitor
my $monitor = {
path => $scanPath,
nextscan => 0,
on_update => $scanPaths->{$scanPath}->{'on_update'},
scanfactor => $scanPaths->{$scanPath}->{'scanfactor'},
scanmin => $scanPaths->{$scanPath}->{'scanmin'},
lastscantime => 0,
evtUpdatePending => 0,
items => {},
excludes => []
};
&log("added scan path: $scanPath");
my @excludes = split /|/, $scanPaths->{$scanPath}->{'excludes'};
foreach my $e (@excludes) {
push @{ $monitor->{'excludes'} }, $e;
&log("excluding on pattern: $e");
}
push @monitors, $monitor;
}
# Always have string 'sleep' in monitor array, the pump below will snooze
# when it encounters this
push @monitors, 'sleep';
########## MAIN MONITOR LOOP ##########
while (1) {
my $monitor = shift @monitors;
# Check for sleep monitor
if ($monitor eq 'sleep') {
sleep 1;
push @monitors, 'sleep';
next;
}
# See if it is time to process this monitor
if (time >= $monitor->{'nextscan'}) {
# Scan the path, start time measure
&log("scanning $monitor->{'path'}") if $debug;
my $st = time;
my $lastScan = $monitor->{'items'};
$monitor->{'items'} = &scanpath($monitor->{'path'},
$monitor->{'excludes'});
# Variables for each event
my $evt_adorm = 0; # added or removed
my $evt_chmod = 0;
my $evt_chown = 0;
my $evt_chgrp = 0;
my $evt_chsiz = 0;
my $evt_chatm = 0;
my $evt_chmtm = 0;
my $evt_chctm = 0;
# Only do the compare if this isn't the first scan
if (scalar(keys(%{ $lastScan }))) {
# Check for updates against the last scan
my @oldFiles = keys %{ $lastScan };
my @newFiles = keys %{ $monitor->{'items'} };
# See if any files were added or removed
if ( (scalar(@oldFiles) != scalar(@newFiles)) || (!
@oldFiles and @newFiles) ) {
&log("$monitor->{'path'} detected files added or
removed");
$evt_adorm = 1;
}
# Test for attribute changes
foreach my $oldFileName (@oldFiles) {
my $oldFile = $lastScan->{$oldFileName};
my $newFile = $monitor->{'items'}->{$oldFileName};
if (! $newFile) {
&log("File $oldFileName not in new set") if
$debug;
next;
}
if ($oldFile->{'mode'} != $newFile->{'mode'}) {
&log("$oldFileName detected mode change")
if $debug;
$evt_chmod = 1;
}
if ($oldFile->{'uid'} != $newFile->{'uid'}) {
&log("$oldFileName detected uid change") if
$debug;
$evt_chown = 1;
}
if ($oldFile->{'gid'} != $newFile->{'gid'}) {
&log("$oldFileName detected gid change") if
$debug;
$evt_chgrp = 1;
}
if ($oldFile->{'size'} != $newFile->{'size'}) {
&log("$oldFileName detected size change")
if $debug;
$evt_chsiz = 1;
}
if ($oldFile->{'atime'} != $newFile->{'atime'}) {
&log("$oldFileName detected access time
change") if $debug;
$evt_chatm = 1;
}
if ($oldFile->{'mtime'} != $newFile->{'mtime'}) {
&log("$oldFileName detected modification
time change") if $debug;
$evt_chmtm = 1;
}
if ($oldFile->{'ctime'} != $newFile->{'ctime'}) {
&log("$oldFileName detected i-node change")
if $debug;
$evt_chctm = 1;
}
}
}
# Composite events
my $evt_update = $evt_chmod || $evt_chown || $evt_chgrp ||
$evt_chsiz || $evt_chmtm || $evt_adorm;
# Capture the elapsed time as soon as we finish
my $et = time - $st;
# Calculate the next scan time
# elapsed time * scan factor OR scanmin, whichever is smaller
my $nextscan = $et * $monitor->{'scanfactor'};
$nextscan = $monitor->{'scanmin'} if $nextscan <
$monitor->{'scanmin'};
$monitor->{'nextscan'} = time + $nextscan;
$monitor->{'lastscantime'} = $et;
&log("scan time for $monitor->{'path'} was $et sec") if $debug;
&log("next scan in T+$nextscan") if $debug;
# Finally, execute requested operations for any events that occured
if ($evt_update) {
$monitor->{'evtUpdatePending'} = 1;
&log("$monitor->{'path'} update detected, pending
stablization for event") if $debug;
}
if ($monitor->{'evtUpdatePending'} > 0 and
$monitor->{'evtUpdatePending'} < 3) {
$monitor->{'evtUpdatePending'}++;
} elsif ($monitor->{'evtUpdatePending'} >= 3) {
&log("$monitor->{'path'} updates appear stable");
&log("exec $monitor->{'on_update'}");
system($monitor->{'on_update'});
$monitor->{'evtUpdatePending'} = 0;
}
}
# Return the monitor to the end of the queue
push @monitors, $monitor;
}
########## FILESYSTEM SCAN FUNCTIONS ##########
# scanpath(pathToScan)
# scans specified path and returns hash where keys are path items
# and contents are file stats
sub scanpath {
my ($path, $excludes) = @_;
opendir DIR, $path;
my @files = grep(!/^..?$/, readdir(DIR));
closedir DIR;
my $stats = {};
foreach my $f (@files) {
my $fp = "$path/$f";
if ($excludes) {
my $excluded = 0;
foreach my $ex (@{ $excludes }) {
if ($fp =~ /$ex/) {
&log("excluded $fp on /$ex/") if $debug;
$excluded++;
last;
}
}
next if $excluded;
}
my @stat = stat($fp);
if (! @stat) {
&log("stat failed, invalidating scan: $path");
return 0;
}
$stats->{$fp} = {};
$stats->{$fp}->{'mode'} = $stat[2];
$stats->{$fp}->{'uid'} = $stat[4];
$stats->{$fp}->{'gid'} = $stat[5];
$stats->{$fp}->{'size'} = $stat[7];
$stats->{$fp}->{'atime'} = $stat[8];
$stats->{$fp}->{'mtime'} = $stat[9];
$stats->{$fp}->{'ctime'} = $stat[10];
if (-d $fp) {
$stats = {%{ $stats }, %{ &scanpath($fp) }};
}
}
return $stats;
}
########## UTILITY FUNCTIONS ##########
# Log sub logs a message and makes sure that the filehandle is still valid
sub log {
my ($msg) = @_;
my ($sec, $min, $hour, $day, $mon, $year) = localtime(time);
$year += 1900;
$mon += 1;
$mon = "0$mon" if $mon < 10;
$day = "0$day" if $day < 10;
$hour = "0$hour" if $hour < 10;
$min = "0$min" if $min < 10;
$sec = "0$sec" if $sec < 10;
if (! -e $logpath) {
print "Log file disappeared! Attempting to re-open.n" if $debug;
close $logfh;
open $logfh, ">>$logpath" or print "Log re-open failed: $!";
}
seek $logfh, 0, 1;
print $logfh "[$year-$mon-$day $hour:$min:$sec] $msgn";
}
/etc/fsupd.conf contains:
logdir = /var/log/fsupd.webmaster
[/var/www/html]
on_update = rsync -a --delete --exclude=/logs --exclude=.* /var/www/html/
mnsvlwwwt001:/apps/apache2/htdocs/
scanfactor = 3
scanmin = 4
excludes = /var/www/html/logs|/.

/etc/rc.d/init.d/fsupd contains:
#!/bin/bash
#
# fsupd System init script for the fsupd daemon
#
# chkconfig: - 99 10
# description: File System Update Daemon
FSUPD=/usr/local/bin/fsupd.pl
PIDFILE=/var/log/fsupd.webmaster/fsupd.pid
start() {
su - webmaster -c "$FSUPD -d"
}
stop() {
kill `cat $PIDFILE`
rm $PIDFILE
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
sleep 1
start
;;
*)
echo "Usage: fsupd {start | stop | restart}"
exit 1
esac
Create AIX 5.1 mksysb iso images for backup/restore
Provided you have enough disk space you could create 2 new volumes - 1 for the backup and the other for the iso images
For example to create a baklv logical volume for backup and a cdlv logical volume for iso images:
mklv -y baklv rootvg 300 (the 300 is enough to store all filesystems in my case)
mklv -y cdlv rootvg 12
mkfs -V jfs2 /dev/baklv
mkfs -V jfs2 /dev/cdlv
Make sure to exclude our new logical volumes from the mksysb image by creating a file /etc/exclude.rootvg with:
/backup
/mkcd
Get into single user mode
shutdown -m
Mount the new filesystems
mount -o log=/dev/hd8 /dev/cdlv /mkcd
mount -o log=/dev/hd8 /dev/baklv /backup
Create the mksysb iso images
mkcd -S -e -C /mkcd -I /backup/mkcd
Configuring Eclipse and TortoiseCVS to manage the same sources

For eclipse and TortoiseCVS 1.8.32 (Could not get 1.10.7 to work) to work together for the same projects in the same workspaces change the following settings in Eclipse:

In Window > Preferences

Then Team > CVS > Ext Connection Method

Select the radio button Use another connection method type to connect and select extssh from the dropdown

Then in the repository browser select the properties for each CVS repository that is configured and change the Connection type to ext

Perform an update against any project and you will get a series of prompts to create keys, etc. click yes for all and you are now setup.

This basically maps ext to extssh for Eclipse and allows other CVS clients that are not compatible with extssh to use the standard ext connection

Now you should be able to perform updates against anything checked out with eclipse using TortoiseCVS 1.8.32 as well

Recover lost hscroot password for an IBM HMC or any unencrypted boot drive
removed hard drive from HMC and used a sata usb adapter to connect it to an Ubuntu virtual machine
mounted /dev/sdb2 to /mnt/sdb2 and /dev/sdb3 /mnt/sdb2/var
chroot /mnt/sdb2
/usr/bin/passwd hscroot
replaced hard drive into hmc and booted - now able to logon with my new password!

Cleanup Old MySQL backups on Windows for AppManager

This will delete all backup files and folders older than 5 days

Path1 = "E:AppManager8workingbackup"


Dim fso
Dim oFolder
Dim oFile
Dim oSubFolder

Set fso = createobject("Scripting.FileSystemObject")

Set oFolder = fso.GetFolder(Path1)

For Each oFile In oFolder.files
If DateDiff("d", oFile.DateCreated,Now) > 5 Then
oFile.Delete True
End If
Next


'Set oFolder = fso.GetFolder(Path2)
' For Each oFile In oFolder.files
' If DateDiff("d", oFile.DateCreated,Now) > 30 Then
' oFile.Delete True
' End If
' Next

Set oFolder = Nothing

'The script will stop running here if you uncomment Wscript.Quit.
'Leave the next line commented if you need to delete subdirectories from the given path.
'Wscript.Quit

Set oFolder = fso.GetFolder(Path1)
Set colSubfolders = oFolder.Subfolders

For Each oSubfolder in colSubfolders
If DateDiff("d", oSubFolder.DateCreated,Now) > 5 Then
fso.DeleteFolder(oSubFolder)
End If
Next

Set oSubFolder = Nothing
Set oFolder = Nothing
Set fso = Nothing
Wscript.Quit

Summarize netstat status on RedHat

netstat -anawk '/tcp/ {print $6}'sortuniq -c

Excluding Load Balancers and Localhost from Apache Access Logs


In httpd.conf add


# Exclude localhost

SetEnvIf Remote_Addr "127.0.0.1" dontlog

# Exclude Test Load Balancer 1

SetEnvIf Remote_Addr "192.168.5.60" dontlog

# Exclude Test Load Balancer 2

SetEnvIf Remote_Addr "192.168.5.80" dontlog


Then in each Virtual Host Custom or the main Custom log entry depending on how you've configured logging append with env=!dontlog as shown below:


CustomLog /log/www-access_log combined env=!dontlog

ServerIron 4G-SSL and Apache Client-IP logging configuration

On load balancers:

csw-rule "r1" url prefix "html"

csw-policy "redirect"

match "r1" forward 1218

match "r1" rewrite request-insert client-ip

default forward 1

default rewrite request-insert client-ip

server real webserver1 192.168.1.10

port http url "HEAD /"

port http server-id 1218

port http group-id 1 1

server real webserver2 192.168.1.20

port http url "HEAD /"

port http server-id 1211

port http group-id 1 1

server virtual webtest1 192.168.1.50

port http cookie-name "ServerID"

port http csw-policy "redirect"

port http request-insert client-ip "X-Forwarded-For"

In apache httpd.conf:

Change From: LogFormat “%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined

To:

LogFormat ""%{X-Forwarded-For}i" %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i"" combined

Then Restart apache2 services