251220061158 (335194668)

When a system evolves and grows, it's usually necessary to identify various versions of software living in the wild. There are many ways to do that: some hide their version numbers in code, some keep them in configuration and metadata files, and others store them in the application's database.

No matter the scheme, accessing and modifying the current version number should be easy and painless- that is, unless you're working with Stan K.'s codebase. In a truly brillant case of reusing existing system facilities, the developers resorted to a much less common method of determining which patches and upgrades have been applied:

my $path = "/var/log/";
my $rval = MyOwn::System::ls({ file => $path });
my @things = split(/\n/, $rval->{'stdout'});

foreach my $item (@things) {
    my $checkver = undef;

    ### ignore everything but Patches and Upgrades
    ### 'prev' indicates that a patch was uninstalled
    if ($item =~ "Patch" && $item !~ "prev" && $item !~ "rollback") {
        my @parts = split(/Patch\-/, $item);
        $checkver = $parts[1];
    } elsif ($item =~ "Upgrade" && $item !~ "prev" && $item !~ "rollback") {
        my @parts = split(/Upgrade\-/, $item);
        $checkver = $parts[1];

Abusing the fact that every upgrade and patch installation leaves a log file behind, the code browses the /var/log/ directory looking for them, and determines the version number using their filenames. While mind-bending, the solution does work- until the application server starts running low on disk space, and the system admins decide to clean up the old logs...

[Advertisement] Manage IT infrastructure as code across all environments with Puppet. Puppet Enterprise now offers more control and insight, with role-based access control, activity logging and all-new Puppet Apps. Start your free trial today!