はじめに
一週間前の自分は他人。
ということで、毎回すんなりとはいかない PHP のデバッグ。
先日書いたVSCodeによるPHPのリモートデバッグを見ながら Remote-SSH 等の基本的な部分の設定を終わり、今回は CLI デバッグに挑戦。いろいろとわかったことがあるのでメモ。
環境
ホスト(母艦)は Windows10 + VSCode 1.56.2。
PHPの実行環境は、CentOS7をVagrant環境から利用。
VSCode からは Remote-SSH 経由で CentOS7 に入り、そこで PHP を動かします。
バージョン情報
vagrant@db1:~ $ php -v
PHP 7.3.28 (cli) (built: Apr 27 2021 13:57:06) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.28, Copyright (c) 1998-2018 Zend Technologies
with Xdebug v3.0.4, Copyright (c) 2002-2021, by Derick Rethans
vagrant@db1:~ $ rpm -qa|grep xdebug
php-pecl-xdebug3-3.0.4-1.el7.remi.7.3.x86_64
xdebug の設定ファイルは /etc/php.d/15-xdebug.ini にあります。解析のためにいくつか変更しました。
vagrant@db1:~ $ sudo tail -5 /etc/php.d/15-xdebug.ini
xdebug.log = /tmp/xdebug.log
xdebug.start_with_request = yes
xdebug.mode = debug
xdebug.force_display_errors = Yes
xdebug.force_error_reporting = Yes
Xdebug3 のデフォルトの待ち受けポート(xdebug.client_port)は Ver.2 までの 9000 から 9003 に変わっていますが、VSCode が作成するデフォルトの launch.json では 9000 のままになっているので、これは Xdebug に合わせておきます。
"configurations": [
{
"name": "Listen for Xdebug",
"type": "php",
"request": "launch",
"port": 9003
},
{
"name": "Launch currently open script",
"type": "php",
"request": "launch",
"program": "${file}",
"cwd": "${fileDirname}",
"port": 9003,
"stopOnEntry": true
}
CLI デバッグの場合は後者の “Launch currently open script” を選んでデバッグします。
また、Xdebug 側の設定は以下の通りになっています。Ver.2 からことごとくディレクティブ名が変更になっているので、renamed や removed は表示から除外してあります。
vagrant@db1:~ $ php -i | grep xdebug | grep -vE '(renamed|removed)'
Additional .ini files parsed => /etc/php.d/15-xdebug.ini,
xdebug
Support Xdebug on Patreon, GitHub, or as a business: https://xdebug.org/support
Enabled Features<br/>(through 'xdebug.mode' setting)
xdebug.cli_color => 0 => 0
xdebug.client_discovery_header => no value => no value
xdebug.client_host => localhost => localhost
xdebug.client_port => 9003 => 9003
xdebug.cloud_id => no value => no value
xdebug.collect_assignments => Off => Off
xdebug.collect_return => Off => Off
xdebug.connect_timeout_ms => 200 => 200
xdebug.discover_client_host => Off => Off
xdebug.dump.COOKIE => no value => no value
xdebug.dump.ENV => no value => no value
xdebug.dump.FILES => no value => no value
xdebug.dump.GET => no value => no value
xdebug.dump.POST => no value => no value
xdebug.dump.REQUEST => no value => no value
xdebug.dump.SERVER => no value => no value
xdebug.dump.SESSION => no value => no value
xdebug.dump_globals => On => On
xdebug.dump_once => On => On
xdebug.dump_undefined => Off => Off
xdebug.file_link_format => no value => no value
xdebug.filename_format => no value => no value
xdebug.force_display_errors => On => On
xdebug.force_error_reporting => 1 => 1
xdebug.gc_stats_output_name => gcstats.%p => gcstats.%p
xdebug.halt_level => 0 => 0
xdebug.idekey => no value => no value
xdebug.log => /tmp/xdebug.log => /tmp/xdebug.log
xdebug.log_level => 7 => 7
xdebug.max_nesting_level => 256 => 256
xdebug.max_stack_frames => -1 => -1
xdebug.mode => debug => debug
xdebug.output_dir => /tmp => /tmp
xdebug.profiler_append => Off => Off
xdebug.profiler_output_name => cachegrind.out.%p => cachegrind.out.%p
xdebug.scream => Off => Off
xdebug.show_error_trace => Off => Off
xdebug.show_exception_trace => Off => Off
xdebug.show_local_vars => Off => Off
xdebug.start_upon_error => default => default
xdebug.start_with_request => yes => yes
xdebug.trace_format => 0 => 0
xdebug.trace_options => 0 => 0
xdebug.trace_output_name => trace.%c => trace.%c
xdebug.trigger_value => no value => no value
xdebug.var_display_max_children => 128 => 128
xdebug.var_display_max_data => 512 => 512
xdebug.var_display_max_depth => 3 => 3
ポートの衝突確認
LISTEN 対象のポート番号が他と衝突していないか事前に確認しておきます。ちなみに今回は Pgpool ノード上で動かしているので 9000 や 9898 等は使用中になっていますが、9003 は大丈夫のようです。また、ファイアーウォールもトラブルの元なので、デバッグ時は一時的に無効にしておきます。
vagrant@db1:~ $ ss -tln
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 *:9000 *:*
LISTEN 0 64 127.0.0.1:9898 *:*
LISTEN 0 64 *:9999 *:*
LISTEN 0 128 *:111 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 60 *:5432 *:*
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 64 [::]:9999 [::]:*
LISTEN 0 128 [::]:111 [::]:*
LISTEN 0 128 [::]:80 [::]:*
LISTEN 0 128 [::]:22 [::]:*
LISTEN 0 60 [::]:5432 [::]:*
LISTEN 0 128 [::]:443 [::]:*
vagrant@db1:~ $ sudo systemctl stop firewalld
デバッグ対象のコード
デバッグ対象の PHP スクリプトは pg-persist.php です。単に PostgreSQL に対して永続的に接続してポーリングするだけのものです。
参考までに、xdebug = trace に変更した上で、コマンドラインから単にスクリプトを実行してみると、/tmp 配下にトレースファイルが作られます。
vagrant@db1:~ $ head /tmp/trace.1166199468.xt
TRACE START [2021-06-03 06:10:51.725850]
0.0003 403704 -> {main}() /home/vagrant/temp/pg-persist.php:0
0.0003 403800 -> MyClass->__construct() /home/vagrant/temp/pg-persist.php:112
0.0003 403800 -> getenv($varname = 'HOME') /home/vagrant/temp/pg-persist.php:38
0.0003 403936 -> is_dir($filename = '/home/vagrant/.pg-persist') /home/vagrant/temp/pg-persist.php:41
0.0004 403968 -> file_exists($filename = '/home/vagrant/.pg-persist/pg-persist.pid') /home/vagrant/temp/pg-persist.php:44
0.0004 403968 -> getmypid() /home/vagrant/temp/pg-persist.php:48
0.0004 403968 -> file_put_contents($filename = '/home/vagrant/.pg-persist/pg-persist.pid', $data = 14394) /home/vagrant/temp/pg-persist.php:48
0.0004 404024 -> MyClass->run() /home/vagrant/temp/pg-persist.php:113
0.0004 404024 -> MyClass->poll() /home/vagrant/temp/pg-persist.php:105
次に、xdebug.mode = debug に戻して(VSCodeではなく)コマンドラインからスクリプトを実行してみると、以下のような警告が出ました。
vagrant@db1:~/temp $ ./pg-persist.php
Xdebug: [Step Debug] Could not connect to debugging client. Tried: localhost:9003 (through xdebug.client_host/xdebug.client_port) :-(
FATAL: pg_hba.conf にホスト"172.16.0.53"、ユーザ"vagrant"、データベース"test1, SSL無効用のエントリがありません
ここで言うところの “debugging client” とは、デバッガ用の IDE(今回は VSCode)のことを指しているようです。xdebug.mode = debug はデバッガとの対話用、xdebug.mode = trace はデバッガを介さないケースでのトレース用ということのようです。
上記のケースでは、単に Xdebug が警告を出すだけで、スクリプトの実行には問題ないようです。
この後 VSCode から通常の手順でデバッグができるようになりました。ではでは。
[追記]Laravel artisan のデバッグ
launch.json
{
"name": "識別名(コマンド名)",
"type": "php",
"request": "launch",
"program": "${file}",
"cwd": "${fileDirname}",
"externalConsole": false,
"port": 9003,
"args": [ "コマンドの署名(signature)" ]
},
エクスプローラーで「artisan」を選択してデバッグ開始。