【问题标题】:How do I use beta Perl modules from beta Perl scripts?如何使用来自 beta Perl 脚本的 beta Perl 模块?
【发布时间】:2011-01-29 07:06:47
【问题描述】:

如果我的 Perl 代码具有生产代码位置和“测试版”代码位置 (例如,生产 Perl 代码我们在 /usr/code/scripts 中,BETA Perl 代码在 /usr/code/beta/scripts 中;生产 Perl 库在 /usr/code/lib/perl 中,而这些库的 BETA 版本在 /usr/code/beta/lib/perl 中,我有没有简单的方法来实现这样的设置?

具体要求是:

  • 生产环境和测试环境中的代码必须相同。

    为了澄清,要将任何代码(库或脚本)从 BETA 升级到生产,唯一需要发生的事情就是从 BETA 向产品位置发出 cp 命令 - 文件名和文件内容必须保持相同

  • 脚本的 BETA 版本必须调用其他 BETA 脚本和 BETA 库(如果存在)或生产库(如果 BETA 库不存在)

  • 测试版和生产版之间的代码路径必须相同,但基目录除外(/usr/code//usr/code/beta/

  • 脚本必须全部位于同一个基本目录下但它们可能位于任意深度级别的子目录中(这排除了第 31.13 节中的经典 use lib "$FindBin::Bin/../lib" 解决方案。使用“Programming Perl”的库

我将介绍我们如何解决这个问题作为这个问题的答案,但我想知道是否有更好的方法。

【问题讨论】:

    标签: perl testing perl-module


    【解决方案1】:

    我们自己的解决方案如下:

    • 拥有一个库(我们称之为 BetaOrProd.pm)

      • 必须通过“use BetaOrProd;”将库包含在每个脚本
      • 库必须是每个脚本中“use strict;”杂注之后的第一个use 语句(如果我们使用它,则“使用警告”)。包括在任何 BEGIN 块之前。
      • 该库有一个 BEGIN 块,其中包含大部分逻辑
      • 库中的 BEGIN 块检查程序的目录路径(基于 $0 并应用绝对路径)
      • 如果目录路径以 /usr/code/beta 开头,则程序被认为在 BETA 位置运行,否则在生产环境中运行
      • 在任何一种情况下,/usr/local/lib/perl 都不会移动到 @INC 列表的开头
      • 如果是 BETA 位置,/usr/code/beta/lib/perl 不会移动到 @INC 列表的开头。
      • 如果是 BETA 位置,特殊变量 $isBETA(可通过从 BetaOrProd.pm 导出的访问器方法访问)设置为“BETA”。
    • 每当一个脚本/库需要调用另一个脚本时,被调用脚本的路径是根据从 BetaOrProd.pm 导出的 $isBETA 变量的所述访问器计算得出的

    • 任何时候需要或使用 Perl 库,都不需要特殊的逻辑 - 由 BetaOrProd.pm 修改的 @INC 负责知道从哪里导入模块。如果模块存在于 BETA 位置,则来自 BETA 位置的库将由 BETA 脚本使用,否则来自 prod 位置的库。

    这种方法的主要缺点是:

    1. 要求每个脚本必须将“use BetaOrProd;”作为每个脚本中“use strict;”杂注之后的第一个use 语句。

      由于我们公司要求每段部署的代码都通过自动验证器,该验证器可以检查此要求,这一事实有所缓解。

    2. 无法通过 /usr/code/beta/lib/perl 对 BetaOrProd.pm 进行 BETA 测试。嗯。

      通过对库进行非常彻底的单元和集成测试来缓解

    【讨论】:

    • @dolmen - 代码是专有的,将其发布到这里最终会导致我死亡,或者更糟糕的是,被解雇。
    【解决方案2】:

    我用FindBin解决这个问题:

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

    或者,如果污点模式处于活动状态:

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

    由于这不依赖于任何已知或固定的路径,它允许在一台机器上任意多的独立代码集,只需创建项目目录的新副本即可。

    我在项目的每个开发映像中维护所有项目模块的完整副本,但听起来你没有,而是依赖于 beta 副本回退到 Live Copy 的模块;在上面的use libs 之前的use lib /path/to/live/bin 可以解决这个问题,或者您可以将/path/to/live/bin 链接到@INC 上的目录之一,以便它始终可以立即使用。

    如果实时版和测试版将从不同的帐户运行,local::lib 可能也值得一看,但这似乎并不是它的真正用途。

    更新:如果脚本本身可能存在于给定目录的多个子目录中,这将不起作用,但在其他情况下起作用。

    【讨论】:

    • 这个解决方案的缺点是它在脚本存在的情况下不起作用,比如一个子目录(/usr/code/scripts/project_trident 而不是/usr/code/scripts)。对于没有在问题中更清楚地说明这一点,我深表歉意 - 我现在明确添加了该条件。
    • 我将不得不对此投反对票,因为它不能回答我原来的问题,但既然说投反对票显然对你不公平(因为我没有明确解释这种情况是我的错误),我会选择你的另一个随机答案似乎值得赞成并给予它应得的:)
    • 如果每个脚本在目录结构中处于已知的固定深度(相对于项目根目录),则可以通过将更多../s 放入use lib 来轻松解决此问题,尽管如果它们的深度超过几个级别,这会很快变得混乱,并且如果脚本的深度发生变化并且您忘记手动更新其 use lib 以获取新的深度,则会中断。
    【解决方案3】:

    我不得不使用类似的配置。但是,该模块以项目名称命名,并且可以执行一些其他任务:加载一些特定于环境的配置变量(例如数据位置、开发/生产数据库的凭据)、处理一些命令行参数和设置对项目中的大多数脚本有用的其他一些变量(YYYYMMDD 格式的当前日期,股票市场当前是否开放等)

    【讨论】:

      猜你喜欢
      • 2021-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-09
      相关资源
      最近更新 更多