How do I use beta Perl modules from beta Perl scripts?

旧城冷巷雨未停 提交于 2019-11-29 07:38:43

Our own solution was as follows:

  • Have a library (let's call it BetaOrProd.pm)

    • The library MUST be included via "use BetaOrProd;" in every script
    • The library MUST be the very first use statement in every script after "use strict;" pragma (and "use warnings" if we use that). Including before any BEGIN blocks.
    • The library has a BEGIN block which contains most of the logic
    • That BEGIN block in the library checks the program's directory path (based off of $0 with absolute path applied)
    • If the directory path starts with /usr/code/beta, the program is deemed to run in BETA location, else in production
    • In either case, /usr/local/lib/perl is un-shifted to the beginning of @INC list
    • If BETA location, /usr/code/beta/lib/perl is un-shifted to the beginning of @INC list after that.
    • If BETA location, a special variable $isBETA (accessible by a accessor method exported from BetaOrProd.pm) is set to "BETA".
  • Anytime a script/library needs to call another script, the path to the called script is calculated based on said accessor to $isBETA variable exported from BetaOrProd.pm

  • Anytime a Perl library needs to be required or used, no special logic is needed - the @INC modified by BetaOrProd.pm takes care of knowing where the modules are to be imported from. If the module is present in BETA location, then the library from BETA location will be used by BETA script, else the library from prod location.

The main drawbacks of this approach are:

  1. Requirement that every script must have "use BetaOrProd;" as the very first use statement in every script after "use strict;" pragma.

    Mitigated by the fact that our company requires every deployed piece of code to pass automated validator, which can check for this requirement.

  2. Can't BETA test BetaOrProd.pm via /usr/code/beta/lib/perl . D'uh.

    Mitigated by very thorough unit and integration test of the library

Dave Sherohman

I address this with FindBin:

use FindBin;
use lib "$FindBin::Bin/../lib";

Or, if taint mode is active:

use FindBin;
use lib ("$FindBin::Bin/../lib" =~ m[^(/.*)])[0];

Since this isn't dependent on any known or fixed paths, it allows for as many independent sets of the code on a single machine as I like, simply by creating a new copy of the project directory.

I maintain complete copies of all project modules in each development image of the project, but it sounds like you don't and instead rely on the beta copy falling back to the live copy's modules; a use lib /path/to/live/bin prior to the use libs above would handle that, or you could just link /path/to/live/bin into one of the directories on @INC so that it will always be available straight away.

If the live and beta versions will be run from different accounts, local::lib may also be worth looking at, but this doesn't really seem to be what it's intended for.

UPDATE: This does not work if the scripts themselves may live in multiple sub-directories of a given directory, but works otherwise.

I have had to use a similar configuration. The module was named after the project name, though, and could perform some other duties: loading some environment-specific configuration variables (locations of data, credentials for dev/prod databases, for example), processing some command-line arguments, and setting some other variables that were useful to most of the scripts in the project (the current date in YYYYMMDD format, whether the stock market was currently open, etc.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!