古いPerlプログラムをサーバー移行したら500 Internal Server Error




10年以上前に作成されたPerlプログラムで書かれたお問い合わせフォームの移行作業の相談がありました。
古いPerlプログラムのサーバー移行は面倒なことが多く、さらに超使いにくいアルファメールがサーバーだったので悩みましたが、お付き合いの長いクライアントだったので引き受けました。
動作確認してみるとやはりエラー。
「500 Internal Server Error」がブラウザ上に表示されていました。
今回はこのエラーの解消方法についてまとめました。

移行先のサーバー環境について

今回の移行先サーバー環境は以下でした。
・アルファメール(大塚商会)
・Perlバージョン : 5.24.0

cgiを実行した結果

ブラウザ上で「500 Internal Server Error」が表示されました。

解析したこと

コントロールパネルからエラーログを確認すると以下を確認できました。

AH01215: Can't use 'defined(%hash)' (Maybe you should just omit the defined()?) at ./jcode.pl line 684
AH01215: Compilation failed in require at xxxx.cgi line 55
AH01215: Can't use 'defined(%hash)' (Maybe you should just omit the defined()?) at ./jcode.pl line 684
Compilation failed in require at xxxx.cgi line 53
End of script output before headers: xxxx.cgi
AH01215: Undefined subroutine &jcode::convert called at xxxx.cgi line 352

エラーから調べてみましたがどうもdefinedが新しいPerlだと不要なことがわかりました。
そこでエラーが出ている箇所のdefinedを削除して再度確認してみましたがエラーは変わらず。
さらに考えみてjcode.plのバージョンを最新化したらどうだろうと思いつきました。
そこでjcode.plの最新バージョンをダウンロードし、動作確認したところ、やはり同じエラーが発生。
definedが最新バージョンでも入っていたので削除したところ、500エラーは解消されました。
修正箇所は以下です。

sub z2h_euc {
    local(*s, $n) = @_;
# 修正箇所1
#    &init_z2h_euc unless defined %z2h_euc;
# ↓ definedを除去
    &init_z2h_euc unless %z2h_euc;
    $s =~ s/($re_euc_c|$re_euc_kana)/
	$z2h_euc{$1} ? ($n++, $z2h_euc{$1}) : $1
    /geo;
    $n;
}

sub z2h_sjis {
    local(*s, $n) = @_;
# 修正箇所2
#    &init_z2h_sjis unless defined %z2h_sjis;
# ↓ definedを除去
    &init_z2h_sjis unless %z2h_sjis;
    $s =~ s/($re_sjis_c)/$z2h_sjis{$1} ? ($n++, $z2h_sjis{$1}) : $1/geo;
    $n;
}

今回の500 Internal Server Errorの原因だったこと

今回のエラーの原因はjcode.plが移行先のPerlバージョンでは対応していなかったこと、およびdefined関数が使えなくなっていたことでした。
解決方法は上記でかい多様にjcode.plを最新化し、defined関数を削除しました。