【学習メモ】CentOS7にapache 2.2.34とmod_perl2.0.10を入れる

# はじめに
CentOS7でApache 2.4系とmod_perlを入れようとしました。
DSOではなくStaticです。

コンパイルやconfigureの時点でエラーが出たので、結局Apache 2.2.34 + mod_perl 2.0.10になってしまいました。

環境はCentOS7(1804, core)にyum groups install baseを適用したものになります。

# 成功例
### Openssl
OpenSSLを入れます。

```bash:OpenSSL1.0.2oのインストール
yum install -y openssl-devel && \
cd /usr/local/src ; wget -P /usr/local/src  https://www.openssl.org/source/openssl-1.0.2o.tar.gz && \
tar xf /usr/local/src/openssl-1.0.2o.tar.gz -C /usr/local/src && \
cd /usr/local/src/openssl-1.0.2o ; \
/usr/local/src/openssl-1.0.2o/config \
--prefix=/opt/openssl-1.0.2o \
--openssldir=/opt/openssl-1.0.2o -fPIC zlib shared  && \
make depend -I /usr/local/src/openssl-1.0.2o && \
make test -I /usr/local/src/openssl-1.0.2o && \
make install -I /usr/local/src/openssl-1.0.2o && \
cd /opt/openssl-1.0.2o ; ln -s lib lib64
```

### Apache 2.2.34
httpdをダウンロードして展開しておきます。

```bash:httpdの準備
wget  -P /usr/local/src http://archive.apache.org/dist/httpd/httpd-2.2.34.tar.bz2 && \
cd /usr/local/src/ ; tar xf /usr/local/src/httpd-2.2.34.tar.bz2 -C /usr/local/src
```

必要なパッケージをインストールしておきます。

```bash:httpdに必要なパッケージ
yum install -y expat-devel
```

### mod_perl
mod_perlをダウンロードします。

```bash:mod_perlのダウンロードと展開
cd /usr/local/src ; wget -P /usr/local/src http://ftp.jaist.ac.jp/pub/apache/perl/mod_perl-2.0.10.tar.gz && \
tar xf mod_perl-2.0.10.tar.gz
```

mod_perlのBug?を2箇所修正しておきます。

```diff:mod_perlソース修正その1
# diff -u Apache-Test/lib/Apache/TestRun.pm.original Apache-Test/lib/Apache/TestRun.pm
--- Apache-Test/lib/Apache/TestRun.pm.original  2018-06-15 03:09:22.174160754 +0900
+++ Apache-Test/lib/Apache/TestRun.pm   2018-06-15 03:10:01.116160754 +0900
@@ -1097,8 +1097,10 @@

     my %args = @Apache::TestMM::Argv;
     while (my($k, $v) = each %args) {
+      if (defined $v) {
         $v =~ s/\|/\\|/g;
         $body .= "\n\$Apache::TestConfig::Argv{'$k'} = q|$v|;\n";
+      }
     }

     my $header = Apache::TestConfig->perlscript_header;
```

```diff:mod_perlソース修正その2
# diff -u src/modules/perl/modperl_common_util.h.original src/modules/perl/modperl_common_util.h
--- src/modules/perl/modperl_common_util.h.original     2018-06-15 03:13:44.436160754 +0900
+++ src/modules/perl/modperl_common_util.h      2018-06-15 03:14:12.221160754 +0900
@@ -19,11 +19,11 @@
 #ifndef MODPERL_COMMON_UTIL_H
 #define MODPERL_COMMON_UTIL_H

-#ifdef MP_DEBUG
+//#ifdef MP_DEBUG
 #define MP_INLINE
-#else
-#define MP_INLINE APR_INLINE
-#endif
+//#else
+//#define MP_INLINE APR_INLINE
+//#endif

 #ifdef CYGWIN
 #define MP_STATIC
```
参考資料
[再度 FreeBSD10.0 で clang 環境構築検証(3) ～ mod_perl2.0.9 は Apache 2.4対応(hankakusai.basekernel.co.jp)](http://hankakusai.basekernel.co.jp/cgi-bin/adiary/adiary.cgi/0569)

mod_perlに必要なパッケージをインストールします。

```bash:mod_perlに必要なパッケージ
yum install -y perl-ExtUtils-Embed
```
依存関係で以下もインストールされます。

```bash:perl-ExtUtils-Embedと一緒に入るパッケージ
gdbm-devel
libdb-devel
perl-ExtUtils-Install
perl-ExtUtils-MakeMaker
perl-ExtUtils-Manifest
perl-ExtUtils-ParseXS
perl-Test-Harness
perl-devel
pyparsing
systemtap-sdt-devel
```

インストールします。

```bash:mod_perlをApacheに組み込んでインストール
cd /usr/local/src/mod_perl-2.0.10/ && \
perl Makefile.PL \
MP_USE_STATIC=1 \
MP_AP_PREFIX="../httpd-2.2.34" \
MP_AP_CONFIGURE=" \
--prefix=/opt/apache-2.2.34 \
--enable-mods-shared=all \
--enable-ssl --with-ssl=/opt/openssl-1.0.2o \
--enable-cache \
--enable-mem-cache --enable-deflate \
--enable-mime-magic --enable-usertrack \
--with-apr=lib/srclib \
--with-apr-util=lib/srclib --with-included-apr \
--with-mpm=prefork --enable-mpms-shared=all \
--enable-so" && make && make install
```

### 動作確認
組み込まれてインストールされたか確認します。

```bash:静的に組み込まれているか確認
# /opt/apache-2.2.34/bin/httpd -l | grep perl
  mod_perl.c

# /opt/apache-2.2.34/bin/apachectl -t
httpd: Could not reliably determine the server's fully qualified domain name, using X.X.X.X for ServerName
Syntax OK

# /opt/apache-2.2.34/bin/apachectl start

# cat /opt/apache-2.2.34/logs/error_log
[Sat Jun 16 02:17:30 2018] [notice] Digest: generating secret for digest authentication ...
[Sat Jun 16 02:17:30 2018] [notice] Digest: done
[Sat Jun 16 02:17:31 2018] [notice] Apache/2.2.34 (Unix) mod_ssl/2.2.34 OpenSSL/1.0.2k-fips DAV/2 mod_perl/2.0.10 Perl/v5.16.3 configured -- resuming normal operations
 
# /opt/apache-2.2.34/bin/apachectl stop
```

マニュアルに沿ってhttpd.confを編集していきます。

```bash:httpd.confの設定追加
# tee -a /opt/apache-2.2.34/conf/httpd.conf <<EOF

Alias /perl/ /opt/apache-2.2.34/perl/
<Location /perl/>
    SetHandler perl-script
    PerlResponseHandler ModPerl::Registry
    PerlOptions +ParseHeaders
    Options +ExecCGI
    Order allow,deny
    Allow from all 
</Location>

EOF

# chmod a+rx /opt/apache-2.2.34/perl/rock.pl

# chmod a+rx /opt/apache-2.2.34/bin/apachectl -t

# /opt/apache-2.2.34/bin/apachectl start

# curl localhost/perl/rock.pl
mod_perl 2.0 rocks!

# /opt/apache-2.2.34/bin/apachectl stop
```
動作確認を2段階にわけるため、```PerlPostConfigRequire```の設定を除いています。

startup.plを準備します。

```bash:startup.plの追加
mkdir /opt/apache-2.2.34/perl/lib
tee -a /opt/apache-2.2.34/perl/lib/startup.pl <<EOF
use lib qw(/opt/apache-2.2.34/perl);

# enable if the mod_perl 1.0 compatibility is needed
# use Apache2::compat ();

# preload all mp2 modules
# use ModPerl::MethodLookup;
# ModPerl::MethodLookup::preload_all_modules();

use ModPerl::Util (); #for CORE::GLOBAL::exit

use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::RequestUtil ();

use Apache2::ServerRec ();
use Apache2::ServerUtil ();
use Apache2::Connection ();
use Apache2::Log ();

use APR::Table ();

use ModPerl::Registry ();

use Apache2::Const -compile => ':common';
use APR::Const -compile => ':common';

1;
EOF

# chmod a+rx /opt/apache-2.2.34/perl/lib/startup.pl
```

```bash:PerlPostConfigRequireの追加
tee -a /opt/apache-2.2.34/conf/httpd.conf <<EOF
PerlPostConfigRequire perl/lib/startup.pl
EOF

# /opt/apache-2.2.34/bin/apachectl -t
```

###### 参考資料
[PerlPostConfigRequire (perl.apache.org)](https://perl.apache.org/docs/2.0/user/config/config.html#toc_C_PerlPostConfigRequire_)
[StartupFile (perl.apache.org)](https://perl.apache.org/docs/2.0/user/handlers/server.html#Startup_File)

MyApache2::Rocksというモジュールを作成します。

```bash:perlのモジュール作成
mkdir /opt/apache-2.2.34/perl/MyApache2
tee /opt/apache-2.2.34/perl/MyApache2/Rocks.pm <<EOF > /dev/null
package MyApache2::Rocks;

use strict;
use warnings;

use Apache2::RequestRec ();
use Apache2::RequestIO ();

use Apache2::Const -compile => qw(OK);

sub handler {
    my \$r = shift;

    \$r->content_type('text/plain');
    print "mod_perl 2.0 rocks!\n";
    print "\$ENV{MOD_PERL}\n";

    return Apache2::Const::OK;
}
1;
EOF
```

```$ENV{MOD_PERL} ```という変数があるらしいので、それを使ってmod_perlのバージョンを表示するようにします。

MyApache2::Rocksを使ったLocationを作成します。

```bash:Location追加
tee -a /opt/apache-2.2.34/conf/httpd.conf <<EOF
<Location /rocks>
    SetHandler perl-script
    PerlResponseHandler  MyApache2::Rocks
</Location>
EOF

# /opt/apache-2.2.34/bin/apachectl -t
```

アクセスしてみます。

```bash:動作確認
# /opt/apache-2.2.34/bin/apachectl start

# curl localhost/rocks
mod_perl 2.0 rocks!
mod_perl/2.0.10

# /opt/apache-2.2.34/bin/apachectl stop
```

成功したようです。

エラーが出たら、apacheのlogsを確認しましょう。


###### 参考資料
[Getting Your Feet Wet with mod_perl(perl.apache.org)](http://perl.apache.org/docs/2.0/user/intro/start_fast.html)


### 起動ファイルの作成
起動ファイルを作ります。

```bash:apacheの起動スクリプト
tee /etc/systemd/system/apache2.2.34.service <<EOF
[Unit]
Description=Apache Web Server 2.2.34 
After=network.target
 
[Service]
Type=forking
ExecStart=/opt/apache-2.2.34/bin/apachectl start
ExecReload=/opt/apache-2.2.34/bin/apachectl graceful
ExecStop=/opt/apache-2.2.34/bin/apachectl stop
PrivateTmp=true
LimitNOFILE=infinity
 
[Install]
WantedBy=multi-user.target
EOF
```

CentOS7+apache2.4系+mod_perl2.0系の成功例があれば教えてください。

# 失敗した例

ソースは```/usr/local/src ```、インストール先は```/opt/apache-2.x.x ```としました。
作業中に出てきたエラーをまとめます。

|Apache|Apr|Apr-util|修正1|修正2|修正3|エラー内容|perl|make|その他|
|:--:|:--:|:--:|:--:|:--|:--|:--|:--|:--|:--|
|2.4.33|1.6.3|1.6.1|なし|なし|なし|その1|失敗|-|-|
|2.4.23|1.6.3|1.6.1|あり|なし|なし|その2|成功|失敗|-|
|2.4.33|1.6.3|1.6.1|あり|なし|なし|その3|成功|失敗|-|
|2.4.33|1.6.3|1.6.1|あり|あり+|なし|その4|成功|失敗|-|
|2.4.33|1.6.3|1.6.1|あり|あり++|なし|その4|成功|失敗|-|
|2.2.9|1.6.3|1.6.1|あり|なし|なし|その5|失敗|-|-|
|2.2.9|included|included|あり|なし|なし|その6|成功|失敗|-|
|2.2.34|included|included|あり|なし|なし|-|成功|成功|成功パターン|
|2.4.33|1.6.3|1.6.1|あり|なし|あり|その7|失敗|-|-|
|2.4.33|1.6.3|1.6.1|あり|なし|あり|その8|成功|失敗|力尽きた|

修正1...あり...Bug? ファイル2つの修正。
修正2...あり...エラーで不足していると言われたapr.hのシンボリックリンクを作成。
修正2...あり\+...不足しているapr/apr-utilの\*.hをシンボリックリンクでインストールのソースファイルに追加する。
修正2...あり\+\+...不足しているapr/apr-utilの\*.hを実ファイルでコピーする。
修正3...あり...srclibへソースを展開したapr/apr-utilをコピー

```bash:修正2のシンボリックリンクでコピーしたコマンド例
cd /usr/local/src/httpd-2.4.33/include/
ls /opt/apr-1.6.3/include/apr-1/*.h | xargs -I {} ln -s  {} `pwd`/
ls /opt/apr-util-1.6.1/include/apr-1/*.h | xargs -I {} ln -s  {} `pwd`/
cd /usr/local/src/mod_perl-2.0.10
```


### エラーその1
apr-1.6.3、apr-util-1.6.1をソースインストールしたあと、perl Makefile.PLで発生する。

```bash:エラーその1
Checking if your kit is complete...
Looks good
ERROR from evaluation of /usr/local/src/mod_perl-2.0.10/Apache-Reload/Makefile.PL: Use of uninitialized value $v in substitution (s///) at Apache-Test/lib/Apache/TestRun.pm line 1100.
```

どうやらBugがある模様で、下記を参考に修正するとでなくなりました。
参考資料
[再度 FreeBSD10.0 で clang 環境構築検証(3) ～ mod_perl2.0.9 は Apache 2.4対応(hankakusai.basekernel.co.jp)](http://hankakusai.basekernel.co.jp/cgi-bin/adiary/adiary.cgi/0569)


### エラーその2
apr-1.6.3、apr-util-1.6.1をソースインストールしたあと、エラーその1のBugを直して、makeしている時に発生。2.4.33でも2.4.23(mod_perlがサポートしている最新)でも発生します。
apr.hなどソースインストールしたapr/apr-utilの中に含まれるファイルがないと言われます。

```bash:エラーその2
gcc -I/usr/local/src/mod_perl-2.0.10/src/modules/perl -I/usr/local/src/mod_perl-2.0.10/xs -I/usr/local/src/mod_perl-2.0.10/../httpd-2.4.33/include -I/usr/local/src/mod_perl-2.0.10/../httpd-2.4.33/os/unix -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/lib64/perl5/CORE -DMOD_PERL -DMP_COMPAT_1X -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -c mod_perl.c
In file included from /usr/local/src/mod_perl-2.0.10/../httpd-2.4.33/include/ap_config.h:25:0,
                 from /usr/local/src/mod_perl-2.0.10/../httpd-2.4.33/include/httpd.h:44,
                 from modperl_apache_includes.h:27,
                 from mod_perl.h:20,
                 from mod_perl.c:17:
/usr/local/src/mod_perl-2.0.10/../httpd-2.4.33/include/ap_hooks.h:39:17: 致命的エラー: apr.h: そのようなファイルやディレクトリはありません
 #include "apr.h"
                 ^
コンパイルを停止しました。
make[1]: *** [mod_perl.o] エラー 1
make[1]: ディレクトリ `/usr/local/src/mod_perl-2.0.10/src/modules/perl' から出ます
make: *** [modperl_lib] エラー 2
```

### エラーその3
apr.hがないと言われたので、apacheソースのincludeディレクトリにapr.hのシンボリックリンクを貼ってみました。

```bash:エラーその3
exports.c:1494:13: エラー: ‘ap_hack_apr_allocator_create’ が再定義されました
 const void *ap_hack_apr_allocator_create = (const void *)apr_allocator_create;
             ^
gawk -f /usr/local/src/httpd-2.4.23/build/make_exports.awk `cat export_files` > exports.c
```

### エラーその4
apacheソースのincludeディレクトリに全部シンボリックリンクを貼って試しました。
makeでシンボリックリンクはよくないと聞いた気がするので、実ファイルをコピーしてみましたがだめでした。

```bash:エラーその4
In file included from /usr/lib64/perl5/CORE/perl.h:5071:0,
                 from modperl_perl_includes.h:65
                 from modperl_common_includes.h:24,
                 from mod_perl.h:21,
                 from modperl_constants.c:1:
modperl_constants.c: 関数 ‘modperl_constants_lookup_apache2_const’ 内:
modperl_constants.c:1146:30: エラー: ‘AP_AUTH_INTERNAL_MASK’ が宣言されていません (この関数内での最初の使用)
               return newSViv(AP_AUTH_INTERNAL_MASK);
(中略)
make[1]: *** [modperl_constants.o] エラー 1
make[1]: ディレクトリ `/usr/local/src/mod_perl-2.0.10/src/modules/perl' から出ます
make: *** [modperl_lib] エラー 2
```

### エラーその5
Apacheのバージョンを下げて再挑戦。
新しいはずのapr-utilが古いと言われます。
2.2系はsrclibディレクトリにaprとapr-utilが入っているのでそれを使うことで回避できました。

```bash:エラーその5
configure: error: APR-util version 1.2.0 or later is required
httpd: ./configure --prefix=/opt/pache-2.2.9 --enable-mods-shared=all --enable-mods-static=all --enable-ssl --with-ssl=/usr/openssl-1.0.2o --enable-cache --enable-mem-cache --enable-deflate --enable-mime-magic --enable-usertrack --with-apr=/opt/apr-1.6.3 --with-apr-util=/opt/apr-util-1.6.1 --with-mpm=prefork --enable-mpms-shared=all --with-expat=builtin --enable-so failed at lib/Apache2/Build.pm line 412.
```

configureオプションに以下を入れるとソースのsrclibを使ってくれます。

```bash:エラーその5の回避方法
--with-apr=lib/srclib \
--with-apr-util=lib/srclib 
```

### エラーその6
OpenSSLのバージョンが0.9系と1.0.0系で内容が違うとのことです。
Apache2.2.9は1.0.0に適用させるためにはソース修正が必要とのことなので諦め、2.2.34に切り替えます。

```bash:エラーその6
ssl_engine_init.c: 関数 ‘ssl_init_ctx_verify’ 内:
ssl_engine_init.c:546:42: エラー: ‘STACK’ が宣言されていません (この関数内での最初の使用)
         SSL_CTX_set_client_CA_list(ctx, (STACK *)ca_list);
                                          ^
ssl_engine_init.c:546:42: 備考: 未宣言の識別子は出現した各関数内で一回のみ報告されます
ssl_engine_init.c:546:49: エラー: expected expression before ‘)’ token
         SSL_CTX_set_client_CA_list(ctx, (STACK *)ca_list);
                                                 ^
make[5]: *** [ssl_engine_init.slo] エラー 1
make[5]: ディレクトリ `/usr/local/src/httpd-2.2.9/modules/ssl' から出ます
make[4]: *** [shared-build-recursive] エラー 1
make[4]: ディレクトリ `/usr/local/src/httpd-2.2.9/modules/ssl' から出ます
make[3]: *** [shared-build-recursive] エラー 1
make[3]: ディレクトリ `/usr/local/src/httpd-2.2.9/modules' から出ます
make[2]: *** [shared-build-recursive] エラー 1
make[2]: ディレクトリ `/usr/local/src/httpd-2.2.9' から出ます
make[1]: *** [all-recursive] エラー 1
make[1]: ディレクトリ `/usr/local/src/httpd-2.2.9' から出ます
make: *** [ap_build] エラー 2
```

###### 参考資料
[openssl-1.0.0 を httpd-2.2.12(apache)以前バージョン で利用する場合のmake時コンパイルエラー対処法(blog.ngsw.jp)](http://blog.ngsw.jp/blog/2012/07/01/openssl-100_httpd-2212apache_make.html)

### エラーその7

configureオプションに ```--with-expat=builtin````が入っていたため出たエラーが出ました。このオプションなしで通るようになります。

```bash:エラーその7
/usr/local/src/httpd-2.4.33/srclib/apr/libtool: line 7475: cd: builtin/lib: No such file or directory
libtool:   error: cannot determine absolute directory name of 'builtin/lib'
```

###### 参考資料
[Thread: Apache 2.4.26(forum.directadmin.com)](http://forum.directadmin.com/showthread.php?t=54952&page=2)

### エラーその8
諦めました。

```bash:エラーその8
In file included from /usr/lib64/perl5/CORE/perl.h:5071:0,
                 from modperl_perl_includes.h:65,
                 from modperl_common_includes.h:24,
                 from mod_perl.h:21,
                 from modperl_constants.c:1:
modperl_constants.c: 関数 ‘modperl_constants_lookup_apache2_const’ 内:
modperl_constants.c:1146:30: エラー: ‘AP_AUTH_INTERNAL_MASK’ が宣言されていません (この関数内での最初の使用)
               return newSViv(AP_AUTH_INTERNAL_MASK);
```