in reply to use lib "."

G'day Bod,

Adding "." to @INC has security implications. It used to be a default but was removed in Perl v5.26.0. There's a long discussion in "perl5260delta: Removal of the current directory (".") from @INC" which I recommend you read.

As already pointed out, cron provides a very limited environment. This not only includes the environment variables available, but also the content of those variables: compare the value of $ENV{PATH} from the command line and from a cron script.

To avoid problems, I typically use absolute paths everywhere in a cron script. You may find code like this in my cron scripts:

... PERL=/usr/bin/perl ... $PERL /full/path/to/some_script.pl ... $PERL /other/full/path/to/other_script.pl ...

A lib directory is fairly standard for Perl modules; it is not standard for scripts. A bin directory is more usual for *.sh, *.pl, and so on. I'll leave you to decide if you wish to make a change.

I knocked up a skeleton directory structure to mirror what you presented. My /home/ken/tmp/pm_11153844_cron_paths/ is intended as an equivalent to your /home/username/website/prod/.

ken@titan ~/tmp/pm_11153844_cron_paths $ pwd /home/ken/tmp/pm_11153844_cron_paths ken@titan ~/tmp/pm_11153844_cron_paths $ ls -lR * lib: total 1 -rw-r--r-- 1 ken None 633 Aug 13 00:38 maintain.pl drwxr-xr-x 1 ken None 0 Aug 13 00:36 Site lib/Site: total 1 -rw-r--r-- 1 ken None 78 Aug 13 00:36 Utils.pm template: total 0 www: total 0

An extremely minimal Site::Utils module looks like this:

ken@titan ~ $ cat /home/ken/tmp/pm_11153844_cron_paths/lib/Site/Utils.pm package Site::Utils; use strict; use warnings; our $VERSION = '1.2.3'; 1;

Here's a maintain.pl which shows how to determine various directories and tests them:

ken@titan ~ $ cat /home/ken/tmp/pm_11153844_cron_paths/lib/maintain.pl # standard pragmata use strict; use warnings; # code to get absolute paths use Cwd 'abs_path'; use File::Basename 'dirname'; my ($BIN_DIR, $LIB_DIR, $TEMPLATE_DIR, $WWW_DIR); BEGIN { $BIN_DIR = dirname abs_path __FILE__; $LIB_DIR = abs_path "$BIN_DIR/../lib"; $TEMPLATE_DIR = abs_path "$BIN_DIR/../template"; $WWW_DIR = abs_path "$BIN_DIR/../www"; } # test paths print "\$BIN_DIR[$BIN_DIR]\n"; print "\$LIB_DIR[$LIB_DIR]\n"; print "\$TEMPLATE_DIR[$TEMPLATE_DIR]\n"; print "\$WWW_DIR[$WWW_DIR]\n"; # test 'Site::Utils' found use lib $LIB_DIR; use Site::Utils; print "Site::Utils version: $Site::Utils::VERSION\n";

Here's that script run from my home directory:

ken@titan ~ $ pwd /home/ken ken@titan ~ $ /usr/bin/perl /home/ken/tmp/pm_11153844_cron_paths/lib/maintain.pl $BIN_DIR[/home/ken/tmp/pm_11153844_cron_paths/lib] $LIB_DIR[/home/ken/tmp/pm_11153844_cron_paths/lib] $TEMPLATE_DIR[/home/ken/tmp/pm_11153844_cron_paths/template] $WWW_DIR[/home/ken/tmp/pm_11153844_cron_paths/www] Site::Utils version: 1.2.3

If you do decide to use a bin directory, that script should still work as is. The first line of output would be:

$BIN_DIR[/home/ken/tmp/pm_11153844_cron_paths/bin]

The other output should be unchanged.

— Ken

Replies are listed 'Best First'.
Re^2: use lib "."
by Bod (Parson) on Aug 12, 2023 at 19:23 UTC
    As already pointed out, cron provides a very limited environment

    That explains the odd behaviour I discovered after posting the question...
    It worked as expected when executed over SSH where the CGI environment variables are still missing.

    To avoid problems, I typically use absolute paths everywhere in a cron script.

    That's how I've solved it - at least I think I've solved it. I won't know for sure until the cron job runs tomorrow morning. Now the maintenance script has an absolute path passed to lib so there are no relative issues to deal with.

    I'm not sure whether this is a better approach than using FindBin?

    A lib directory is fairly standard for Perl modules; it is not standard for scripts. A bin directory is more usual for *.sh, *.pl, and so on. I'll leave you to decide if you wish to make a change.

    See my reply to hippo at Re^2: use lib "."

    I'd be interested in your view of having a bin or cron directory when there is only a single script outside the www directory...

      "I'd be interested in your view of having a bin or cron directory when there is only a single script outside the www directory..."

      I'd pick a standard location for scripts (bin, cron, scripts, whatever) and use it consistently. I wouldn't move them around based on how many there were at any given time.

      — Ken

        I'd pick a standard location for scripts

        Thanks Ken,

        I shall roll out a cron and a bin directory as I make changes...

Re^2: use lib "."
by Bod (Parson) on Aug 12, 2023 at 19:35 UTC
    Adding "." to @INC has security implications. It used to be a default but was removed in Perl v5.26.0.

    Thanks for the information. I wasn't aware of the change...I thought it was still there for all versions of Perl. I am using v5.16.3 in this environment so "." is still included as is shown from perl -V

    @INC: /home/account/perl5/lib/perl5/5.16.3/x86_64-linux-thread-multi /home/account/perl5/lib/perl5/5.16.3 /home/account/perl5/lib/perl5/x86_64-linux-thread-multi /home/account/perl5/lib/perl5 /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .
    But this could potentially bite me locally where I have v5.32.1. The difference is definitely there...
    @INC: C:/Strawberry/perl/site/lib/MSWin32-x64-multi-thread C:/Strawberry/perl/site/lib C:/Strawberry/perl/vendor/lib C:/Strawberry/perl/lib

      For actual commercial stuff (i.e. where there is real customer PII and/or financial data at stake), I think the only responsible approach is to keep to a supported version of Perl. That means released in the last 2 years (I believe), so it will get security patches. You'd then need to keep up with the latest sub-version in order to get those patches.

      I'd say it's the same as keeping your OS patched, and I hope you do that too.