|
| 1 | +#!/usr/bin/env perl |
| 2 | + |
| 3 | +# Read Postgresql log and compile preferred name change report. |
| 4 | + |
| 5 | +# Invoke with -y or --yesterday to compile with yesterday's timestamps. |
| 6 | +# Useful if you run this script overnight starting after 12AM. |
| 7 | + |
| 8 | +# Author: Peter Bailie, RPI Research Computing |
| 9 | +# Date: April 29, 2022 |
| 10 | + |
| 11 | +use strict; |
| 12 | +use warnings; |
| 13 | +use autodie; |
| 14 | +use v5.30.0; |
| 15 | +use POSIX qw(strftime); |
| 16 | + |
| 17 | +# CONFIG -- denotes full path and file |
| 18 | +my $PSQL_LOG = "/var/log/postgresql/postgresql-12-main.log"; |
| 19 | +my $PNC_LOG = "preferred_name_change_report.log"; |
| 20 | + |
| 21 | +# Main |
| 22 | +print STDERR "Root required.\n" and exit 1 if ($> != 0); |
| 23 | + |
| 24 | +my $epoch_offset = 0; |
| 25 | +$epoch_offset = -86400 if (scalar @ARGV > 0 && ($ARGV[0] eq "-y" || $ARGV[0] eq "--yesterday")); |
| 26 | +my $datestamp = strftime "%Y-%m-%d", gmtime(time + $epoch_offset); |
| 27 | + |
| 28 | +open my $psql_fh, "<:encoding(UTF-8)", $PSQL_LOG; |
| 29 | +open my $pnc_fh, ">>:encoding(UTF-8)", $PNC_LOG; |
| 30 | + |
| 31 | +my ($timestamp, $userid, $auth) = ("", "", ""); |
| 32 | +my ($oldfn, $newfn, $oldln, $newln, $line1, $line2); |
| 33 | +while (<$psql_fh>) { |
| 34 | + ($timestamp, $userid, $oldfn, $newfn, $oldln, $newln) = ($1, $2, $3, $4, $5, $6) if (/^${datestamp} (\d{2}:\d{2}:\d{2}\.\d{3} [A-Z]{3}).+DETAIL: USER_ID: "(.+?)" (?:PREFERRED_FIRSTNAME OLD: "(.*?)" NEW: "(.*?)" )?(?:PREFERRED_LASTNAME OLD: "(.*?)" NEW: "(.*?)")?$/); |
| 35 | + $auth = $1 if (/\/\* AUTH: "(.+)" \*\//); |
| 36 | + # $auth is always on a different line than $timestamp, $userid. |
| 37 | + # But all three having data will indicate we have collected pref name change logs. |
| 38 | + if ($timestamp ne "" && $userid ne "" && $auth ne "") { |
| 39 | + # $oldfn, $newfn, $oldln, $oldfn -- some may be undefined. |
| 40 | + # This happens when either the firstname or lastname change wasn't recorded in PSQL logs (because no change occured). |
| 41 | + # Undefined vars need to be defined to prevent 'concatenation by undefned var' warning. |
| 42 | + foreach ($oldfn, $newfn, $oldln, $newln) { |
| 43 | + $_ = "" if (!defined $_); |
| 44 | + } |
| 45 | + |
| 46 | + # If both old and new firstnames are blank, no change was logged. |
| 47 | + if ($oldfn ne "" || $newfn ne "") { |
| 48 | + ($oldfn, $newfn) = rpad(19, $oldfn, $newfn); |
| 49 | + $line1 = " OLD PREF FIRSTNAME: ${oldfn}"; |
| 50 | + $line2 = " NEW PREF FIRSTNAME: ${newfn}"; |
| 51 | + } else { |
| 52 | + ($line1, $line2) = ("", ""); |
| 53 | + ($line1, $line2) = rpad(41, $line1, $line2); |
| 54 | + } |
| 55 | + |
| 56 | + # If both old and new lastnames are blank, no change was logged. |
| 57 | + if ($oldln ne "" || $newln ne "") { |
| 58 | + ($oldln, $oldfn) = rpad(19, $oldln, $oldfn); |
| 59 | + $line1 .= " OLD PREF LASTNAME: ${oldln}\n"; |
| 60 | + $line2 .= " NEW PREF LASTNAME: ${newln}\n"; |
| 61 | + } else { |
| 62 | + $line1 .= "\n"; |
| 63 | + $line2 .= "\n"; |
| 64 | + } |
| 65 | + |
| 66 | + ($userid) = rpad(9, $userid); |
| 67 | + print $pnc_fh "${datestamp} ${timestamp} USER: ${userid} CHANGED BY: ${auth}\n"; |
| 68 | + print $pnc_fh $line1; |
| 69 | + print $pnc_fh $line2; |
| 70 | + ($timestamp, $userid, $auth) = ("", "", ""); |
| 71 | + } |
| 72 | +} |
| 73 | + |
| 74 | +close ($pnc_fh); |
| 75 | +close ($psql_fh); |
| 76 | +exit 0; |
| 77 | + |
| 78 | +# Right-pad string(s) with whitespaces. |
| 79 | +# expected parameters: (1) padding value, (2...n) strings to pad |
| 80 | +# return: list of padded strings |
| 81 | +sub rpad { |
| 82 | + my $numpadding = shift; |
| 83 | + $_ = sprintf("%-${numpadding}s", $_) foreach @_; |
| 84 | + return @_; |
| 85 | +} |
0 commit comments