Perl
CentOS
Perl 5Day 13

CentOS 標準搭載の Perl に負けないで強く生きる

More than 3 years have passed since last update.

この記事では、OS 標準の Perl で動く CLI ツールを作ってる際に CentOS でハマる点について説明しています。

TL;DR

  • Linux / Mac OS X の多くの環境では標準で Perl 5 がインストールされいる
  • しかし CentOS 標準の Perl 5 の コアモジュールは欠けている
  • OS 標準の Perl に依存した CLI ツールを作る時は注意が必要

なぜ標準インストールの Perl を使う必要があるのか

現在使われている Linux の多くや Mac OS X には、標準で Perl 5 がインストールされています。

しかし、Perl でウェブサービスを開発する際には、それら標準でインストールされている Perl ではなく、独自でインストールやビルドした Perl を使うことになるでしょう。

しかし、日常的に Perl を使っている人向けではない CLI ツールであったとしたら話は別です。
そのツールを使うために、別途 Perl のインストールをさせるのは避けたい。

たとえば、私が開発しているコマンドラインツールである crenv のバックエンドである crystal-build は、上記の理由により OS 標準の Perl を使って動いています。

corelist コマンド

corelist コマンドを使うと、モジュールが Perl のコアモジュールであるかどうかを調べることができます。

以下のように実行すると、JSON::PP は Perl v5.13.9 以降はコアモジュールであり、JSON::XS はコアモジュールに含まれないことが分かります。

$ corelist JSON::PP

JSON::PP was first released with perl v5.13.9

$ corelist JSON::XS

JSON::XS was not in CORE (or so I think)

つまり、corelist で調べてからモジュールを使えば、環境によるコアモジュール差異の問題は生じないはずです。と思っていた時代が私にもありました。

CentOS の標準 Perl のコアモジュール

しかし CentOS の標準の Perl には、コアモジュール が欠けている問題があります。
具体的にどのようなモジュールが欠けているのか、簡単なスクリプトを記述して確かめてみます。

以下のスクリプトに対して $ ./corelist.pl 5.016003 のように実行すると、ある特定のバージョンに含まれているべきコアモジュールを検査するスクリプトが書きだされます。

(CentOS の標準 Perl のコアモジュールに Module::CoreList が含まれていないため、このように遠回りな手法を取っています)

corelist.pl
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;

use Data::Dumper;
use Module::CoreList;

local $Data::Dumper::Terse = 1;

my $perl_version    = $ARGV[0];
my $module_versions = Module::CoreList::find_version($perl_version);
my @module_names    = sort keys %$module_versions;
my $data            = do { local $/; <DATA> };
my $source          = sprintf($data, Dumper(\@module_names));

print "$source\n";

__DATA__
#!/usr/bin/env perl
use strict;
use warnings;
use utf8;

open(STDERR, '>/dev/null');

my $module_names = %s;

for my $module_name (@$module_names) {
    eval "require $module_name";

    if ($@) {
        print "$module_name ERROR\n";
    }
}

実行して出力したスクリプトを調べたい環境で実行すると、どのモジュールが存在しないかが分かります。

以下は、Amazon Linux AMI 2015.09.1 の初期状態の Perl v5.16.3 で存在しないモジュールの一例です (括弧内は、コアモジュールとして存在するはずのバージョン)。

  • Archive::Tar (>= v5.9.3)
  • JSON::PP (>= v5.13.9)
  • Module::Load (>= v5.9.4)
  • Test::More (>= v5.6.2)
  • version (>= v5.9.0)

たとえば、Perl で書かれた nodebrew は、コアモジュールが欠けた状態の CentOS で動作させるため このように Archive::Tar モジュールから tar コマンドへフォールバックするコードが記述されています。

CentOS の標準 Perl で標準モジュールを有効にする方法

実は CentOS では一部の Perl コアモジュールは別のパッケージとして独立しています。
以下のようにしてインストールが可能です。

[ec2-user@ip-172-31-15-126 ~]$ sudo yum search perl-core
Loaded plugins: priorities, update-motd, upgrade-helper
==================== N/S matched: perl-core ====================
perl-core.x86_64 : Base perl metapackage

  Name and summary matches only, use "search all" for everything.

[ec2-user@ip-172-31-15-126 ~]$ sudo yum install perl-core -y

なぜ CentOS の Perl ではコアモジュールが省かれているのか (考察)

これは、Ubuntu と違い CentOS が Perl ではなく Python に強く依存する OS であるからであると考えられます。

私は、Perl コアモジュールとして定義されているものは、どの環境にインストールされた Perl でも存在するべきであると思います。なぜならば、コアモジュールがインストールされている前提でスクリプトを記述するからです。

しかし、このような状況であるため CentOS のコアモジュールが欠けた状態を考慮してコードを書く必要がありますので、ご注意を…。

まとめ

  • Linux / Mac OS X の多くの環境では標準で Perl 5 がインストールされいる
  • しかし CentOS 標準の Perl 5 の コアモジュールは欠けている
  • OS 標準の Perl に依存した CLI ツールを作る時は注意が必要