【问题标题】:Why do official perl docker images have two version of perl?为什么官方的 perl docker 镜像有两个版本的 perl?
【发布时间】:2019-08-06 00:09:31
【问题描述】:

我正在开发一个使用 Docker perl:5.10-threaded 映像的遗留产品,当我发现有两个版本的 perl - 一个在 /usr/local/bin/perl 和一个在 /usr/bin/perl 时,在尝试调试时遇到了问题。在这个特定的图像中,它们实际上是不同的版本

  • /usr/local/bin/perl -> 5.10.1
  • /usr/bin/perl -> 5.20.2

它导致的问题是每个都有不同的@INC 路径。

$ /usr/local/bin/perl -V 
    [snip]
    /usr/local/lib/perl5/5.10.1/x86_64-linux-thread-multi
    /usr/local/lib/perl5/5.10.1
    /usr/local/lib/perl5/site_perl/5.10.1/x86_64-linux-thread-multi
    /usr/local/lib/perl5/site_perl/5.10.1
$ /usr/bin/perl -V
    [snip]
    /etc/perl
    /usr/local/lib/x86_64-linux-gnu/perl/5.20.2
    /usr/local/share/perl/5.20.2
    /usr/lib/x86_64-linux-gnu/perl5/5.20
    /usr/share/perl5
    /usr/lib/x86_64-linux-gnu/perl/5.20
    /usr/share/perl/5.20
    /usr/local/lib/site_perl
    .

最新版本,如perl:5.30-threaded 也有两个版本和不同的@INC 路径。

  • /usr/local/bin/perl -> 5.30.0
  • /usr/bin/perl -> 5.28.1

原来我的旧版应用使用了#!/usr/bin/perl,当perl foo.plfoo.pl 的工作方式不同时,这让我非常困惑(它抱怨缺少库)。

为了增加一点色彩,这个旧版应用程序还通过apt-get 安装了一堆perl 库。例如,

libcpanel-json-xs-perl libxml-libxml-perl libcgi-pm-perl 
libtie-ixhash-perl
libswitch-perl libmime-lite-perl liblist-moreutils-perl
libdate-calc-perl libnet-sftp-foreign-perl
libxml-libxslt-perl liburi-escape-xs-perl
libdatetime-perl

这些似乎安装了/usr/bin/perl 可以访问的东西,这可能是应用程序在shebang 行中使用它的原因。

此应用程序所做的另一件事是安装一些 cpanm 项目,然后将它们复制过来,以便 /usr/bin/perl 可以访问它们

RUN cpanm XML::XML2JSON
RUN cpanm JSON                       

RUN cp /usr/local/lib/perl5/site_perl/5.10.1/XML/XML2JSON.pm /usr/lib/x86_64-linux-gnu/perl5/5.20/XML
RUN cp /usr/local/lib/perl5/site_perl/5.10.1/JSON.pm /usr/lib/x86_64-linux-gnu/perl5/5.20

这对我来说似乎是一个 hack,但我是 perl 开发的新手,所以谁知道呢?

所有这些都引出了我的问题:

  • 为什么 Docker 镜像中有两个版本的perl
  • apt-getcpanm 是否相互不兼容?
  • 有没有更好的方法来安装这些 perl 库?

【问题讨论】:

    标签: perl docker


    【解决方案1】:

    Perl 是许多 Linux 发行版的重要组成部分,必须预先安装。操作系统使用的系统 perl 通常安装为/usr/bin/perl。它的模块通过包管理器(例如apt)而不是通过cpan/cpanm 进行管理。如果您自己为系统 perl 安装模块,这可能与操作系统预期的模块冲突。更糟糕的是,安装错误的模块版本可能会破坏部分操作系统。同样,替换系统 perl 是一个坏主意。这就是为什么那些 Docker 镜像会同时安装不同的 perl。

    对于您的应用程序,您应该避免使用系统 perl。如果您想安装额外的模块以与系统 perl 一起使用,请考虑使用 local::lib。在某些情况下,您可能会通过 apt 安装依赖项,例如 C 库或外部工具,但不会使用 apt 提供的 Perl 模块。

    除非您针对特定操作系统,否则不要硬编码#!/usr/bin/perl shebang。相反,更喜欢#!/usr/bin/env perl,这样脚本将使用 PATH 中的第一个 perl。或者,使用包装脚本显式调用正确的 perl 安装。例如:

    #!/bin/sh
    exec /usr/local/bin/perl -I/path/to/extra/modules /path/to/my/script "$@"
    

    请注意,您不能在不同版本的 Perl 之间共享模块。在安装 XS 模块期间,它们会针对特定版本进行编译,并且无法使用不同的 Perl 版本加载。对于您的本地 perl,只需通过 cpanm 安装依赖项并忽略为系统 perl 安装的模块。

    【讨论】:

    • 阿蒙,感谢您的回答 - 我没有认为 perl 是发行版不可或缺的一部分。我继承了这个,所以我将清理 shebang 硬编码。有没有一种方便的方法可以将apt-get 包映射到cpan 包?例如,liburi-escape-xs-perl?
    • @DougDonohoe 根据 Debian/Ubuntu 命名约定,APT 包 libfoo-bar-perl 包含 CPAN 模块 Foo::Bar。您无法以编程方式翻译此内容,因为大小写可能不同,但您可以在 MetaCPAN 上轻松查找确切名称。
    猜你喜欢
    • 2019-04-24
    • 2017-12-18
    • 2016-09-21
    • 1970-01-01
    • 2022-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多