Posted: 2018-05-31 08:01:22 by Alasdair Keyes
For such a versatile language, Perl has no good built-in way of running an external commands.
You can obviously use exec()
, system()
or even the dreaded back ticks ``
. But often when running commands you require different things. Maybe you just need an exit code, so system()
is good. If you're looking to capture output, exec()
or backticks are more suited for the job, but then escaping input and using pipes or redirects then becomes a nightmare.
Last year worked on a project that required a large amount of systems integration and calling binaries, to run tasks and process output so I had to find a reliable and useful method. Mixing system()
, exec()
was possible but as I would be handing the code off to the customer, having a single way of running commands is a lot cleaner.
I came across https://metacpan.org/pod/Capture::Tiny. It provides a clean interface for capturing output from both Perl code and running system binaries.
#!/usr/bin/env perl
use strict;
use warnings;
use Capture::Tiny ':all';
use v5.20;
my ($stdout, $stderr, $exit_code) = capture {
system("ls", "/var");
};
say "STDOUT\n$stdout";
say "STDERR\n$stderr";
say "EXITCODE: $exit_code";
STDOUT
backups
cache
games
lib
local
lock
log
mail
opt
run
spool
tmp
STDERR
EXITCODE: 0
The only flaw seems to be that it doesn't handle the capturing of output long running processes that will spit out text slowly. For that you will want to use something like pump on https://metacpan.org/pod/IPC::Run
If you found this useful, please feel free to donate via bitcoin to 1NT2ErDzLDBPB8CDLk6j1qUdT6FmxkMmNz
© Alasdair Keyes
I'm now available for IT consultancy and software development services - Cloudee LTD.
Happy user of Digital Ocean (Affiliate link)