「PHP のソースコードをデバッグしてみたら?」と悪魔の囁きが聞こえてきたので、まずはビルド環境作りから。
やること
- Vagrant + VirtualBox で VM(CentOS 7.6)を作る
- Ansible を使って必要なパッケージのインストールや設定を行う1
- PHP のソースコードを入手してビルドする
前提
この記事を書いた人のレベルは、以下のとおりです。
- 基本的な Linux コマンドの操作は知っている
- 設定ファイルを編集するのに
vi
を使います
- 設定ファイルを編集するのに
- Vagrant は仕事で少し触った程度
- Ansible は「なにそれ?おいしいの?」状態
- Git も仕事で少し触った程度
VM を作る
Ansibleをはじめる人に。 に書いてある手順と、ほぼ同じです。(分かりやすい記事に感謝です)
Vagrant と VirtualBox をインストールする
Vagrant と VirtualBox をインストールします。
ディレクトリを作る
VM 用のディレクトリを作ります。
mkdir -p ~/vagrant/centos76
Vagrantfile を生成する
vagrant init
で Vagrantfile を生成します。
VM のもととなる BOX ファイルは bento/centos-7.6
(検索結果)を使います。
vagrant init bento/centos-7.6 --box-version 201812.27.0
Vagrantfile を編集する
今回は VM を2つ作ります。
-
controller
- Ansible を実行する VM
- IPアドレス:
192.168.33.10
-
target
- Ansible の実行対象で、PHP をビルドする VM
- IPアドレス:
192.168.33.20
~/vagrant/centos76
の下に生成された Vagrantfile
を以下のように書き換えます。
Vagrant.configure("2") do |config|
config.vm.define "controller" do |node|
node.vm.box = "bento/centos-7.6"
node.vm.box_version = "201812.27.0"
node.vm.hostname = "controller"
node.vm.network "private_network", ip: "192.168.33.10"
node.vm.network "forwarded_port", id: "ssh", guest: 22, host: 2210
end
config.vm.define "target" do |node|
node.vm.box = "bento/centos-7.6"
node.vm.box_version = "201812.27.0"
node.vm.hostname = "target"
node.vm.network "private_network", ip: "192.168.33.20"
node.vm.network "forwarded_port", id: "ssh", guest: 22, host: 2220
end
end
VM を起動する
vagrant up
で VM を起動します。
vagrant status
を実行して、controller
と target
両方とも起動していれば問題ありません。
$ vagrant status
Current machine states:
controller running (virtualbox)
target running (virtualbox)
This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.
Ansible を設定する
Ansible をインストールする
controller
に SSH でログインします。
$ vagrant ssh controller
root ユーザーに切り替えて、yum
で Ansible をインストールします。
$ su
Password: (vagrant)
# yum install ansible
ansible --version
を実行すると、以下のように表示されます。
# ansible --version
ansible 2.4.2.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/home/vagrant/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
SSH 接続を設定する
controller
からさらに target
へ SSH 接続できたほうが便利なので、いろいろ設定しておきます。
まずは、SSH の公開鍵を作って、target
に登録しておきます。
# ssh-keygen -t rsa
# ssh-copy-id root@192.168.33.20
また、毎回 IP アドレスを入力するのは面倒なので、/etc/hosts
に target
を追加して、名前解決できるようにしておきます。
# vi /etc/hosts
127.0.0.1 controller controller
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.33.20 target
inventory ファイルを作る
Ansible 用のディレクトリを作ります。今回は以下のようなディレクトリ構成にします。
/ansible/
|- invengtory/
| |- hosts : 対象ホストを記述した設定ファイル
|
|- target/
|- test.yml : Playbook ファイル
まずは /ansible/inventory/hosts
ファイルを準備します。
# mkdir -p /ansible/inventory
# cd /ansible
# vi inventory/hosts
targets
というグループのメンバーに target
(192.168.33.20
)を追加します。
[targets]
192.168.33.20
Playbook ファイルを作る
Ansible は、Playbook に理想的な状態を定義して対象ホストがそれを満たす状態を作る という考え方のツールです。なので、Playbook ファイルが一番重要になります。
# mkdir target
# vi target/test.yml
Playbook ファイルに設定する内容は後回しにして、先に Playbook ファイルを準備したあとの手順を書いておきます。
書いた Playbook ファイルは ansible-playbook
コマンドを使って、対象ホスト(今回は target
)へ反映します。
まずは、反映する前に、書いた Playbook ファイルが問題ないかを --check
オプションを付けて確認します。
# ansible-playbook --check -i inventory/hosts target/test.yml
エラーが出ないことを確認したら、以下のようにして反映します。
# ansible-playbook -i inventory/hosts target/test.yml
対象ホストへSSH接続する
今は controller
に SSH 接続している状態ですが、ここからさらに target
へ SSH 接続します。
Playbook を作る際は、その内容で問題ないかを確かめるために、頻繁に対象ホストへ接続することになります。
一旦、controller
を抜けるよりも、controller
に入ったまま target
へ接続できたほうが便利ですね。
図にすると、こんな感じです。
Mac -- (SSH) --> controller -- (SSH) --> target
/etc/hosts
に設定しておいたので、実行するコマンドはとてもシンプルです。
# ssh target
PHP をビルドする
前提
PHP をビルドするために必要なパッケージについては マニュアル に記載があるので、確認しておきましょう。
Playbook ファイルを作る
target/test.yml
に以下のように定義します。
- hosts: targets
user: root
tasks:
- name: Set Timezone
timezone:
name: Asia/Tokyo
- name: Install gcc
yum: name=gcc
- name: Install autoconf
yum: name=autoconf
- name: Install automake
yum: name=automake
- name: Install ctags
yum: name=ctags
- name: Install gdb
yum: name=gdb
- name: Install git
yum: name=git
- name: Install bison
yum: name=bison
- name: Install libxml2-devel
yum: name=libxml2-devel
- name: Install sqlite-devel
yum: name=sqlite-devel
- name: Install epel-release
yum: name=epel-release
- name: Install re2c
yum: name=re2c
- name: Reinstall glibc-common
shell: yum -y reinstall glibc-common
- name: Set Locale
shell: localectl set-locale LANG=ja_JP.utf8
Playbook ファイルを作ったあとは、ansible-playbook
で target
に反映します。
# ansible-playbook -i inventory/hosts target/test.yml
ソースコードを入手する
PHP のソースコードは GitHub にあるので、git clone
で入手します。
# ssh target
# git clone https://github.com/php/php-src.git
configure する
今回はデバッグ目的なので --enable-debug
オプションを付けて ./configure
を実行します。
# cd php-src
# ./buildconf
# ./configure --enable-debug
make する
./configure
が成功したら、make
を実行します。
# make
以下のように表示されたらビルド成功です。
Build complete.
Don't forget to run 'make test'
make test する
「make test
を実行するのを忘れないで!」と言われたので、make test
もやっておきましょう。
=====================================================================
TEST RESULT SUMMARY
---------------------------------------------------------------------
Exts skipped : 50
Exts tested : 26
---------------------------------------------------------------------
Number of tests : 16099 10784
Tests skipped : 5315 ( 33.0%) --------
Tests warned : 0 ( 0.0%) ( 0.0%)
Tests failed : 1 ( 0.0%) ( 0.0%)
Expected fail : 36 ( 0.2%) ( 0.3%)
Tests passed : 10747 ( 66.8%) ( 99.7%)
---------------------------------------------------------------------
Time taken : 602 seconds
=====================================================================
=====================================================================
EXPECTED FAILED TEST SUMMARY
---------------------------------------------------------------------
Test open_basedir configuration [tests/security/open_basedir_linkinfo.phpt] XFAIL REASON: BUG: open_basedir cannot delete symlink to prohibited file. See also
bugs 48111 and 52176.
(省略)
=====================================================================
=====================================================================
FAILED TEST SUMMARY
---------------------------------------------------------------------
Timeout again inside register_shutdown_function [tests/lang/045.phpt]
=====================================================================
You may have found a problem in PHP.
This report can be automatically sent to the PHP QA team at
http://qa.php.net/reports and http://news.php.net/php.qa.reports
This gives us a better understanding of PHP's behavior.
If you don't want to send the report immediately you can choose
option "s" to save it. You can then email it to qa-reports@lists.php.net later.
Do you want to send this report now? [Yns]:
なんか失敗したらしい
PHP を実行する
気を取り直して、php-src/sapi/cli
の中に php
コマンドが作成されているので実行してみましょう。
# sapi/cli/php --version
PHP 8.0.0-dev (cli) (built: Feb 3 2019 10:59:53) ( NTS DEBUG )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies
とりあえず、ちゃんと動いているらしいです。
更新をローカルに取り込む
今回ビルドしたソースコードは開発版なので、頻繁に更新がされます。
まず、以下のコマンドで最新のソースコードを入手します。
# git fetch
# git merge origin/master
あとは、 ./configure --enable-debug
から再度実行するだけです。
躓きポイント
devel に要注意
./configure
を実行した際に、libxml2
や sqlite
がインストールされていないと表示されました。
しかし、yum
で確認するとインストール済みとなっています。
いろいろ調べたところ、libxml2-devel
と sqlite-devel
をインストールする必要がありました。
re2cがyumにない
yum install re2c
を実行しても存在しないと表示されました。
PHP7をCentOS7にインストールする手順 によると、EPEL(Extra Packages for Enterprise Linux)をインストールすると、yum install re2c
が実行できるようになるとのことでした。
ロケールが設定できない
これは PHP というよりは CentOS の問題ですが、automake
を実行した際にロケール設定に失敗したと表示されます。
日本語のロケールが入っていないことが原因らしく、glibc-common
を再インストールしてからロケールを設定すると、うまくいきました。
ただ、Playbook の yum モジュール には再インストールが見当たらなかったので、shell モジュール で行うようにしました。
(「冪等性」を考えると微妙な気もしますが、Ansible をまだよく理解できていないので、一旦、こうしておきます。)
まとめ
いろいろ苦戦しましたが、どうにか PHP のビルド環境を作ることができました。次は GDB を使ってデバッグしてみたいです。(GDB の使い方から勉強しないと・・・)
参考
-
Ansible
-
Vagrant
-
PHP のビルド
更新履歴
- 2019/02/03
-
master
ブランチが 8.0.0 になったので、PHP のバージョン情報を更新しました。
-
-
Ansible 使う必然性はないのですが、なんとなく使ってみたかったので。 ↩