VSCodeによるPHPのCLIデバッグ

はじめに

一週間前の自分は他人。

ということで、毎回すんなりとはいかない 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」を選択してデバッグ開始。

タイトルとURLをコピーしました