ルモーリン
ホーム 更新 Perl ランドナー サービス 雑談 コースガイド 鉄ゲタ 自転車 Linux リンク 連絡先

ApacheのCGIにperlbrewを使う

2018-12-25

背景

サーバーがCentOS6.5、一緒に入っているPerl(システムPerl)が5.10です。 日進月歩のPerlの新機能を使おうすると「何それ、知らないよ?(・_・ ) ( ・_・)」とか言われてしまう。 この記事を書いている時点で最新版は5.28です。 できれば最新版を使いたい。 もし最新版で都合が悪ければ一歩後退(一つ前のバージョンに変更)とか自在にしたい。

警告(隠密同心 心得之條)

  1. 検索しても同様の手法がない
  2. セキュリティホールの可能性が高い
  3. 尚、死して屍、拾う者なし
  4. 尚、死して屍、拾う者なし

基本的な考え方

CGIはhttpdサーバーのApacheが起動して、そのサーバーのApacheを実行するアカウントはapacheです。 つまりアカウントapacheがperlbrewを使えるようになればCGIとしてperlbrewのPerlを使えそうです。

アカウントapacheでログイン

/etc/passwdを編集してシェルを使えるようにして、コマンドpasswdでパスワードを設定して、su -l apacheでログインします。 日常でログインしないアカウントにログインの機会を与えておくのはセキュリティの隙を突かれるので作業後に戻します。 なお、アカウントapacheのホームディレクトリは/home/apacheでなく/var/wwwです。

perlbrewをインストール

このページを参考にインストールします。
perlbrew - ユーザー環境にPerlをインストールする - Perlゼミ(サンプルコードPerl入門)

新しいperlをインストール

最新版を…と思いましたがパソコンのPerlバージョンを合わせておくとバージョン違いのトラブルを回避できそうです。 パソコンはActivePerlの5.26を使っているのでそれに合わせます。 ところがインストールを始めるとテストのioのshm(共有メモリ)にokが出た直後から反応しなくなり、 これはテスト失敗でなくテスト動作で沈黙するためインストール時オプションの--forceでも沈黙してしまいますから、 仕方がないのでテストを回避する--notestでインストールします。

cpanmをインストール

perlbrew install-cpanm

パッケージをインストール

必要なパッケージをドンドコ入れましょう。とりあえず
perl -c <CGIスクリプト>
を実行して「『@INCにないよ』エラー」が出てくるパッケージを全部入れましょう。
cpanm <パッケージ名>
それとインストール済かどうか自動チェックして動作が変わる場合はチェック対象のモジュールも追加しましょう。 誰だよそんな面倒な動作するモン作ったのは? すみません、私です。m(_ _)m

ソフトリンクを設定

CGIの1行目、よくあるのは「#!/usr/bin/perl」をインストールしたperlに変更します。 一般的なシェル下でperlbrewを使う場合は「/usr/bin/env perl」と書き、環境変数を利用して起動してます。 これはバージョン切り替えを実現するための仕掛けです。 apacheではシェルの環境変数が反映されていないので起動できません。 ソフトリンクで希望のバージョンのPerlを選択して呼べるようにします。
リンクの設定
cd /var/www/perl5/perlbrew
ln --symbolic perls/perl-5.26.2/bin/perl perl
これでCGIの1行目を「#!/var/www/perl5/perlbrew/perl -w」にできます。

テストプログラム

テスト用のCGIを実行して動作チェック。
CGIのプログラムtest.cgi
#!/var/www/perl5/perlbrew/perl -w

use utf8;
use strict;
use warnings;
use open IO => ":utf8";

use CGI '-utf8';
use Encode;
use Encode::Argv;
use Encode::Locale;

use FindBin;
use lib $FindBin::Bin;

use MyTest;

$| = 1;

my $cgi = CGI->new;
print $cgi->header(
	-charset => "utf-8",
	-language => "ja",
);
print $cgi->start_html(
	-title => "CGIのテスト",
);
print $cgi->h1("CGIのテスト");
print $cgi->p("上手く実行できたかな?");
print $cgi->p("モジュールの実行もOK?");
MyTest::test $cgi;
print $cgi->end_html;
モジュールMyTest.pm
package MyTest;

use utf8;
use strict;
use warnings;

sub test($) {
	my ($cgi) = @_;
	print $cgi->p("OK!(ズドン!)");
}

1;

動作確認

無事成功♪