はじめに
この記事は Perl Advent Calendar 2022 の 1日目の記事です。
ある Perl 屋の副業の物語
この物語は実際のお仕事を元につくられたフィクションです。
あなたは時々、副業で Perl 関連の仕事を請けている。 最近は Perl を自ら進んで書く人は減ってしまったが、競争も少ない分買い叩かれることもなく、 悪くない仕事だと思っている。
今回の仕事の内容は、顧客に依頼されたメールサーバーに Perl で書かれたプログラムを導入して設定することだ。導入したいプログラムは authentication_milter、初めて知ったプログラムだ。これは CPAN にも Mail::Milter::Authentication として登録されている。対象となるメールサーバーの OS は CentOS Stream 8 だが、このモジュールの rpm はどこにも無いようだ。さて、どうやってインストールするのが良いだろう…?
制約条件
-
対象プログラム(authentication_milter)はメールサーバーソフト(postfix)から呼び出され、OS の標準サービスの一部として働く予定だ。
- そのため、OS添付の
/usr/bin/perl
(いわゆるシステムPerl)を活用したい
(plenv/ perlbrew/ perl-build などで独自の Perl バイナリーをインストールすることは、運用を他人に引き継いだ後の混乱の元になるという理由で、今回は避けるとする)
幸い、CentOS Stream 8 の現在の Perl はv5.26.3
。新しくはないが、使えないほど古いものでもない。
- そのため、OS添付の
-
このサーバーには既に SpamAssassin (これも Perl で書かれている)が OS のパッケージ管理システム dnf を通じて導入されている。この挙動は壊したくない。
-
テストサーバー上で authentication_milter を導入し、問題が発覚した時は撤退することで顧客の同意を得ている。ただし、撤退時は完全なアンインストールが必須だ。
普通に cpanm する方法の問題点
公式サイトでは普通に cpanm でインストールする方法が紹介されている。運が良ければこれで動くだろう。
cpanm Mail::Milter::Authentication
けど、運が悪かったら? undo してやり直したくなったら? (cpanm には --uninstall
オプションがあるが、自分で使ったことはない。どの程度信用できるだろうか?)。また、実験サーバーで動いたとして、本番サーバーでも cpanm を実行した時に同じバージョンのモジュールが入るとは限らない。第一、たまたま通信エラーが起きたらどうする?そのためだけにローカルに CPAN サーバーを用意するのは…負担が大きい…
OrePAN を使って、予め CPAN のローカルミラーを作って git 管理する方法があるそうだが…
もっと直接的に、 インストール結果ディレクトリ自体を git 管理
する方法が、あるのではないか?
着眼
CPAN モジュールのインストール結果ディレクトリ自体を git 管理すれば、 branch を使って undo も redo も自由自在だ。 git submodule で github から CPAN モジュールを取り込む事も出来るだろう。 sha1 のお陰で改ざん防止にもなるし、システム変更の履歴も残せる。 良いことばかりじゃないか?
提案:git 管理された /usr/local/perl5
標準的な Linux ディストリビューションの /usr/bin/perl
で
cpanm や cpm を使ってグローバルにインストールした CPAN モジュール群は、
Perl Config の installsitearch
installsitelib
の指すディレクトリにインストールされる。(※)
% perl -MConfig -le 'print "$_=$Config{q(installsite).$_}"
for qw(arch lib)'
# CentOS Stream 8 の場合(Perl 5.26)
arch=/usr/local/lib64/perl5
lib=/usr/local/share/perl5
# Fedora 36 の場合
arch=/usr/local/lib64/perl5/5.34
lib=/usr/local/share/perl5/5.34
そこで、これらのディレクトリを symlink にし、
実体は /usr/local/perl5
に置いて、そこを git の管理下に置くのはどうだろうか…?
% cd /usr/local
% ls -ld lib64/perl5 share/perl5
lrwxrwxrwx. 1 root root 20 8月 23 14:09 lib64/perl5 -> ../perl5/lib64/perl5
lrwxrwxrwx. 1 root root 20 8月 23 14:09 share/perl5 -> ../perl5/share/perl5
% tree -L 2 perl5
perl5
├── cpanfile
├── lib64
│ └── perl5
├── make-symlink.zsh
├── run-cpm.zsh
└── share
└── perl5
※ sitearchexp, sitelibexp を参照した方が良いかもしれません
実装の例
私が業務で 2016年頃から用いてきたスクリプト群を手直しし、テンプレート化したものを github に置きました。(fedora:latest コンテナ内で動作確認済みです)
github.com/hkoba/usr-local-perl5-template
-
一部のスクリプト※が Fedora, CentOS Stream などの RedHat 系を前提にしています。
Debian, Ubuntu 系で用いたい場合は、代わりのものを実装して下さい。 -
*.zsh
とあるスクリプトは実行に zsh が必要です
※ dnf-install.zsh
使い方
-
clone して
cpanfile
に欲しいモジュールを追記し、run-cpm.zsh
を 実行して下さい。dnf install zsh perl git cd /usr/local git clone https://github.com/hkoba/usr-local-perl5-template.git perl5 cd $_ # EDIT cpanfile and dnf-install-perlmodules.lst # Then ./run-cpm.zsh
-
例えばシステムの openssl に依存するもののように、OS のパッケージ管理でインストールしたほうが簡単な CPAN モジュールも有るでしょう。そういうものは 下記のファイルにモジュール名を列挙して下さい。
dnf-install-perlmodules.lst
-
別マシンでインストール結果を再現したい場合は、git clone 後に以下のコマンドで symlink を作成して下さい
./dnf-install.zsh ./make-symlink.zsh
おしまい
最後まで読んで下さり、ありがとうございました!