Todd's Odds & Ends: A pattern for Perl based plugin assets

If you have Perl plugins that are essential to monitoring your environment, you are probably struggling to find a way to make them available as Sensu assets. One point of frustration may be how to make sure your servers and/or containers have all of the prerequisite Perl modules necessary for the plugins to work. If this is the case, the solution below may work for you.

This solution actually makes self-contained binaries from your Perl scripts that you can then package up as an asset. This is accomplished with PAR::Packer.

Installing Par::Packer is like any other Perl module, install cpanm then install pp. Yes, Perl can be finicky about dependency installs and it varies by platform, so getting to that point will be left as an exercise to the reader. But in the end you should come out with this:

$ sudo cpanm pp
[...dependency installs...]
Building and testing PAR-Packer-1.049 ... OK
Successfully installed PAR-Packer-1.049
7 distributions installed

Once ‘pp’ is installed you should be able to use it to create a binary from an existing Perl script. Your Perl script has to be functional on the host you are using to do the compile. That, in and of itself, may also require additional modules, again left as an exercise to the reader. In my examples below, I will use the plugin found on Nagios Exchange.

First, verify that the Perl version of the script is operational:

$ ./
CERTIFICATES OK - OK:, expires=Tue 11 Feb 2020 00:14:54 UTC (32 days);

Now compile that script into a binary and confirm it is similarly operational:

$ pp -o check_certificates
# Use of runtime loader module Module::Implementation detected.  Results of static scanning may be incomplete.
# Use of runtime loader module Module::Runtime detected.  Results of static scanning may be incomplete.

$ file check_certificates
check_certificates: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=38a747b679225b772145d707405a77235d6e7b28, stripped

$ ./check_certificates
CERTIFICATES OK - OK:, expires=Tue 11 Feb 2020 00:14:54 UTC (32 days);

Now that you have a working binary, you can package it up in asset format to be hosted on your asset server.

$ mkdir bin
$ mv check_certificates bin/
$ tar czvf check_certificates.tar.gz bin
$ sha512sum check_certificates.tar.gz
9a7c687ac5213fbede99f012b24aaa3e4d23120d611a5d6a6ff7a795a60b7a6a7e6701a2dcfbb9570dc38b39272c4d06bc399bf474359544fc9a9c1ce46c5675  check_certificates.tar.gz

Warning, this may not work for every Perl script, so be sure to test the generated binary to ensure its functionality.


I found a wrinkle!

I was playing with pp on Fedora 31 and trying to build perl executable that works on Centos 7 i ran into the fact that the libperl from Fedora 31 uses shared libraries. This is bundled into the par executable built by pp depends on specific GLIBC version symboling that CentOS glibc doesn’t provide sa well as a that is not available in CentOS.

Ironically the pp built executable built on CentOS doesn’t have the GLIBC problem because newer versions of glibc in Fedora 31 has the symbol support for the older glibc used in CentOS.

This implies that you’ll need to also take care with perl as built on alpine and won’t be able to assume you can use the par executable across all distributions. Not a huge problem, as you can build different assets for different target platforms still if you need to. You’ll also need to review the shared libraries used by libperl on the build host and determine which ones you need to include in the asset /lib directory if you are trying to support targets that do not have perl installed already.