Creating an Automated Scripting Application with Perl

From Development to Deployment

Gathering Insight
5 min read3 days ago
Photo by Markus Spiske on Unsplash

In this guide, we’ll build an automated scripting application using Perl to execute predefined scripts for tasks like data processing, system maintenance, report generation, or automated testing. We’ll use Strawberry Perl and Berrybrew for Windows environments, and perlbrew for Linux or WSL (Windows Subsystem for Linux). Let’s get started!

Prerequisites

Before proceeding, ensure your system is ready. The setup depends on your operating system:

  • Linux or WSL: You’re set to use perlbrew for managing Perl versions. Install a Linux distribution on WSL if using Windows (e.g., Ubuntu via Microsoft Store), then install perlbrew (see Step 12).
  • Windows (without WSL): You won’t have native Unix tools, so install these:

Strawberry Perl: A full Perl environment for Windows. Download from strawberryperl.com.

Berrybrew: A Perl version manager for Windows. Get it from GitHub.

Verify installations:

  • Windows: perl -v (after Strawberry Perl) and berrybrew version (after Berrybrew).
  • Linux/WSL: perl -v (after perlbrew setup).

Step-by-Step Guide

Step 1: Install Strawberry Perl (Windows Only)

  • If on Linux or WSL: Skip to Step 3.
  • Download and install Strawberry Perl from strawberryperl.com. Follow the installer’s instructions.
  • Verify: Open a terminal (e.g., Command Prompt) and run perl -v. You should see the Perl version.

Step 2: Install Berrybrew (Windows Only)

  • If on Linux or WSL: Skip to Step 3.
  • Download Berrybrew from its GitHub page and follow the installation steps.
  • Verify: Run berrybrew version in your terminal.

Step 3: Set Up the Project Directory

Create an organized structure for your project. Open a terminal and run:

mkdir AutoPerl
cd AutoPerl
mkdir bin config lib local logs scripts t
  • Purpose: These directories hold your scripts (scripts), configuration (config), libraries (lib), logs (logs), and more.
  • Note: We’ll use “AutoPerl” as the project name throughout.

Step 4: Create the Configuration File

In the config directory, create app_config.yaml to define scripts and log location:

# Configuration settings for AutoPerl
scripts:
- name: Example Script
path: scripts/example_script.pl
- name: Another Script
path: scripts/another_script.pl
logs: logs/example.log

Step 5: Create the Main Script

In the bin directory, create run.pl. This script loads the config, initializes the runner, and executes scripts:

#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../lib"; # Add lib to @INC
use lib "$FindBin::Bin/../local/lib/perl5"; # Add local lib to @INC
use AutomatedScriptingApp::ScriptRunner;
use AutomatedScriptingApp::Config;

# Load configuration
my $config_file = "$FindBin::Bin/../config/app_config.yaml";
my $config = AutomatedScriptingApp::Config->new($config_file) or die "Failed to load config: $!\n";

# Initialize the script runner
my $script_runner = AutomatedScriptingApp::ScriptRunner->new($config) or die "Failed to initialize script runner\n";

# Run the scripts
$script_runner->run_scripts();
  • Improvements: Added basic error handling for config and runner initialization.

Step 6: Create the Config Module

In lib/AutomatedScriptingApp, create Config.pm to load the YAML file:

package AutomatedScriptingApp::Config;
use strict;
use warnings;
use YAML::XS 'LoadFile';

sub new {
my ($class, $file) = @_;
my $self = bless {}, $class;
eval { $self->{config} = LoadFile($file) };
if ($@) {
warn "Error loading config file '$file': $@";
return undef;
}
return $self;
}
sub get_config { shift->{config} }
1;
  • Improvements: Returns the object ($self) properly, adds an accessor (get_config), and handles YAML loading errors.

Step 7: Create the Script Runner Module

In lib/AutomatedScriptingApp, create ScriptRunner.pm to execute scripts:

package AutomatedScriptingApp::ScriptRunner;
use strict;
use warnings;
use AutomatedScriptingApp::Utils;

sub new {
my ($class, $config) = @_;
my $self = bless { config => $config }, $class;
return $self;
}
sub run_scripts {
my ($self) = @_;
my $config = $self->{config}->get_config;
my $scripts = $config->{scripts} or die "No scripts defined in config\n";
foreach my $script (@$scripts) {
my $path = $script->{path} or next;
unless (-e $path) {
AutomatedScriptingApp::Utils::log_message("Error: Script '$path' not found");
next;
}
AutomatedScriptingApp::Utils::log_message("Running script: $path");
system("perl", $path) == 0 or warn "Script '$path' failed: $?\n";
}
}
1;
  • Improvements: Validates script paths, uses config accessor, improves error handling for script execution.

Step 8: Create the Utils Module

In lib/AutomatedScriptingApp, create Utils.pm for logging:

package AutomatedScriptingApp::Utils;
use strict;
use warnings;
use Exporter 'import';
use File::Basename;
use File::Spec;

our @EXPORT_OK = qw(log_message);
sub log_message {
my ($message) = @_;
my $log_file = File::Spec->catfile(dirname(__FILE__), '../../logs/example.log');
open my $fh, '>>', $log_file or do {
warn "Could not open log file '$log_file': $!";
return;
};
print $fh "$message\n";
close $fh;
}
1;
  • Improvements: Adds error handling for log file access, avoids die for non-fatal logging failures.

Step 9: Create Example Scripts

In the scripts directory, create these sample scripts:

example_script.pl

#!/usr/bin/env perl
use strict;
use warnings;
print "Hello from example_script.pl!\n";

another_script.pl

#!/usr/bin/env perl
use strict;
use warnings;
print "Hello from another_script.pl!\n";

Step 10: Prepare the Log Directory

In the logs directory, create README.md:

# Log Directory

This directory stores logs generated by AutoPerl. The main log file is `example.log`.

Step 11: Clear the Log File

In scripts, create clear_log.pl:

#!/usr/bin/env perl
use strict;
use warnings;

my $log_file = 'logs/example.log';
if (-e $log_file) {
open my $fh, '>', $log_file or die "Could not clear log file: $!";
close $fh;
print "Log file cleared successfully.\n";
} else {
print "No log file to clear.\n";
}
  • Improvements: Checks if the file exists before clearing.

Step 12: Configure Perl Environment

  • Windows (Berrybrew):
berrybrew install 5.32.1_64
berrybrew switch 5.32.1_64

Verify: perl -v shows 5.32.1.

  • Linux/WSL (perlbrew):
    Install perlbrew:
curl -L https://install.perlbrew.pl | bash source ~/perl5/perlbrew/etc/bashrc
  • Then install and switch Perl:
perlbrew install perl-5.32.1 perlbrew switch perl-5.32.1
  • Verify: perl -v.

Step 13: Install Required Perl Modules

Install cpanm if not present:

  • Windows: cpan App::cpanminus
  • Linux/WSL: perlbrew install-cpanm

Then install dependencies:

cpanm YAML::XS
  • Note: Explicitly installs YAML::XS, the only external dependency.

Step 14: Run the Application

Navigate to your project directory (replace with your actual path):

cd /path/to/AutoPerl  # e.g., C:\Git\AutoPerl or ~/AutoPerl
perl bin/run.pl

Packaging Your Application

Once tested, package your app for distribution:

Dist::Zilla (Latest: 6.032):

  • Install: cpanm Dist::Zilla
  • Create a dist.ini and run dzil build for a distributable tarball. Ideal for complex projects.

Module::Build (Latest: 0.4234) or ExtUtils::MakeMaker (Latest: 7.70):

  • Generate a Build.PL or Makefile.PL with module-starter, then perl Build.PL && ./Build dist.

Docker:

  • Example Dockerfile:
FROM perl:5.32
COPY . /app
WORKDIR /app
RUN cpanm YAML::XS
CMD ["perl", "bin/run.pl"]
  • Build: docker build -t autoperl.
  1. Script Wrapping:
  • Use pp (from PAR::Packer): pp -o autoperl bin/run.pl to bundle with dependencies.

Deployment Options

Deploy based on your needs:

  1. Local Servers/Workstations: Run directly for internal automation.
  2. Cloud Services: Use AWS Lambda (via Perl layers), Google Cloud Run, or Azure VMs. Check Perl version support.
  3. Virtual Machines: Spin up a VM with your preferred OS and Perl setup.
  4. Containerization: Deploy with Docker or Kubernetes for scalability (e.g., docker run autoperl).

Troubleshooting

  • “Module not found”: Run cpanm YAML::XS again.
  • “Permission denied”: Ensure you have write access to the logs directory.
  • No output: Check logs/example.log for errors.

Conclusion

You’ve built a robust, automated scripting application in Perl! It’s configurable, logs execution details, and can scale with new scripts or features. Try tweaking the config or adding scripts to suit your needs.

Here is an example of the build, the repos kind of messy and doesn’t make complete sense but I’ll update everything later. For now, use the repo as a reference with the article.

License

This project is licensed under the MIT License.

--

--

Gathering Insight
Gathering Insight

Written by Gathering Insight

A place to leave my understandings and correlations from my notes.

Responses (1)