perllaunchdmacos-sequoia

debugging a MacOS launchd script


I have run out of things to look for or don't know where to look anymore. I have a perl script that checks a particular website to see if it has changed, and throws an alert one way or another. Looking something like:screenshot

#!/Users/<me>/perl5/perlbrew/perls/perl-5.40.0/bin/perl


use v5.40;

use common::sense;
use LWP::Simple;
use Digest::MD5 qw(md5_hex);
use Encode;
use Path::Tiny;



my $url  = 'https://<some_website>.com';  # Change to your target URL
my $file = '/Users/<me>/Desktop/CODING/PERL/oil_price/last_hash.txt';
my $icon_path = 
'/Users/<me>/Desktop/CODING/PERL/oil_price/fuelpump.iconset/icon_32x32@2x.png';
my $ua = LWP::UserAgent->new();
$ua->timeout(10);
$ua->agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64)");

my $response = $ua->get($url) or die "Couldn't fetch $url\n\n";
my $content = $response->decoded_content;
my $current_hash = md5_hex(Encode::encode_utf8($content));
my $last_hash = '';

if (-e $file) {
  open my $fh, '<', $file or die "Could not open $file: $!";
  $last_hash = <$fh>;
  close $fh;
}

if ($last_hash ne $current_hash) {
  print "Price of oil has changed!\n";
  my $message = "Webpage $url has changed!";
  my @cmd = (
    "alerter",
    "-title", "Oil_Price",
    "-message", "The price of oil has changed",
    "-sound", "default",
    "-appIcon", $icon_path,
    "-contentImage", $icon_path,
    "-timeout", 10,
  );
  system(@cmd) == 0
  or warn "system @cmd failed: $?";
  open my $fh, '>', $file or die "Could not write to $file: $!";
  print $fh $current_hash;
  close $fh;
}
else {
my @cmd = (
    "alerter",
    "-title", "Oil_Price",
    "-message", "No change in oil price",
    "-sound", "default",
    "-appIcon", $icon_path,
    "-contentImage",$icon_path,
    "-timeout", 10,
);
system(@cmd) == 0
  or warn "system @cmd failed: $?";;
}
my $exit_value  = $? >> 8;
my $signal_num  = $? & 127;
my $dumped_core = $? & 128;
say $exit_value;
say $signal_num;
say $dumped_core;

sleep 10;

path('/Users/harrybennett/Desktop/CODING/PERL/oil_price/.log')->append("$0 ran at " . localtime);

This code executes properly from the command line but no joy via launchd.

I had a plist file for this, but it seems to have gotten lost along the way. In the course of researching the issue(s) I was having, I picked up on the suggestion of using automator to put a wrapper around it. Which I did.

/bin/bash -c "$1"

With a plist file of:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>local.oil_price</string>
    <key>ProgramArguments</key>
    <array>
      <string>open</string>
      <string>-a</string>
      <string>/Users/<me>/Desktop/CODING/PERL/oil_price/oil_price.app</string>
       <string>/Users/<me>/Desktop/CODING/PERL/oil_price/oil_price.pl</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>/tmp/local.oil_price.err</string>
    <key>StandardOutPath</key>
    <string>/tmp/local.oil_price.out</string>
    <key>StartInterval</key>
    <integer>3600</integer>
  </dict>
</plist>

From the command line using : open -a ~/Desktop/CODING/PERL/oil_price/oil_price.app ~/Desktop/CODING/PERL/oil_price/oil_price.pl

The application works as I expect it to. From launchd however, not so much. I get a little spinning gear up on the menubar showing me that it's doing "something".

@-iMac LaunchAgents % launchctl list|grep price

telling me that it is not running at this particular instant but that it ran and exited successfully.

I can not find anything in a log entry anywhere. With the distinct possibility of ignorance as to where to look.

I know that the script executes from the launchd as last_hash.txt gets (re-)written. local.oil_price.err and local.oil_price.out both have been (re-)created but contain zero bytes. I just NEVER get the popup from launchd or and error saying why it didn't.


Solution

  • You should be able to find any errors in the file to which you redirected stderr in your plist, so use a command like this to see them:

    more /tmp/local.oil_price.err
    

    The issue is likely that launchd is unable to find some executable program you are using, such as alerter which is probably provided by homebrew and in a place where macOS is not going to look, such as /opt/homebrew/bin. The reason is that launchd does not go through your normal login sequence, so its PATH is not set like it is in your shell.

    So... run

    type alerter
    

    in your Terminal to get its full path. Use that full path in your Perl script.