この記事では、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 が含まれていないため、このように遠回りな手法を取っています)
#!/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 ツールを作る時は注意が必要