Отладка PHP приложений на удаленном хосте при помощи XDebug и vim в Linux

Введение


В PHP приложениях отладка при помощи var_dump, debug_backtrace и прочих полезных функций не всегда удобна, и возникает потребность в полноценном отладчике. Эта статья — для тех, кто по каким-либо причинам не хочет использовать IDE, поддерживающие отладку PHP приложений из коробки, вроде NetBeans или PhpStorm, а хочет использовать для этих целей vim, и при этом отладка происходит на удаленном хосте.

Для vim существует плагин «DBGp client», но он позволяет нормально отлаживать только в случае, когда пути до всех файлов на удаленной и на локальной машинах одинаковые. Например, если локальной машине у вас есть:
/home/user/application/
/home/user/framework/

а на удаленной машине они расположены в:
/var/www/html/application/
/var/www/framework/

то отладить приложение при помощи «DBGp client» не получится, так как он ничего не знает о другом расположении исходников.

В данной статье мы рассмотрим:
  1. Кратко — настройку всего необходимого для удаленной отладки приложения.
  2. Модификацию плагина для поддержки различных путей.
  3. Кратко — использование отладчика.

Установка


Настраиваем vim на локальном хосте

Скачайте и установите плагин:
$ cd ~/.vim
$ wget www.vim.org/scripts/download_script.php?src_id=7285 -O debugger.zip
$ unzip debugger.zip
$ rm debugger.zip


Внимание: vim должен быть собран с поддержкой python, проверить это можно при помощи ":version", в выводе должна быть строка "+python".

Устанавливаем и настраиваем Xdebug на удаленном хосте

Установите расширение Xdebug любым удобным для вас способом. Например, на Debian Squeeze это делается просто:
# apt-get install php5-xdebug
А в общем случае, лучше почитать официальную инструкцию по установке.

Настройте подключение к локальному debug-клиенту — для этого в php.ini пропишите следующие строчки, заменив 192.168.1.110 на IP локальной машины (при необходимости порт тоже можно перенастроить):
xdebug.remote_enable = 1
xdebug.remote_port = 9000
xdebug.remote_host = 192.168.1.110


Настраиваем соответствие файлов

Идея простая — при отправке запроса дебагеру (например, на установку breakpoint), мы должны преобразовывать путь на локальном хосте в путь на удаленном хосте, и наоборот, при получении информации от дебагера (например, о том что сейчас он находится на какой-то строке какого-то файла), мы должны сделать обратное преобразование.
Дописываем в конец файла debugger.py следующий код:
class FileMapping: 
    def __init__(self, mapping_file): 
        self.local_to_remote = {} 
        self.remote_to_local = {} 

        mapping = open(mapping_file, 'r') 
        for line in mapping: 
            local, remote = line.split(' ') 

            local = local.strip() 
            remote = remote.strip() 

            if not (local in self.local_to_remote): 
                self.local_to_remote[local] = [] 
            self.local_to_remote[local].append(remote) 

            if not (remote in self.remote_to_local): 
                self.remote_to_local[remote] = [] 
            self.remote_to_local[remote].append(local) 

    def local_to_remote_file(self, local): 
        for local_path in self.local_to_remote.keys(): 
            if local.startswith(local_path): 
                # use the first mapping as we don't know which one we should take 
                remote_path = self.local_to_remote[local_path][0] 
                return remote_path + local[len(local_path):] 

    def remote_to_local_file(self, remote): 
        for remote_path in self.remote_to_local.keys(): 
            if remote.startswith(remote_path): 
                for local_path in self.remote_to_local[remote_path]: 
                    local = local_path + remote[len(remote_path):] 
                    # use the first existing file 
                    if os.path.exists(local): 
                        return local 
        return None 

file_mapping = FileMapping('/home/alexey/mapping')


А в файл mapping (/home/alexey/mapping — замените на свой путь) записываем соответствие локальный и удаленных директорий, например:
/home/alexey/framework /var/www/framework
/home/alexey/application /var/www/html


Просматриваем код плагина в поисках мест, где от Xdebug приходят имена файла. В итоге, все они сводятся к вызову одного метода — set_srcview, в начало которого мы и добавляем изменение имени файла:
def set_srcview(self, file, line):

    """ set srcview windows to file:line and replace current sign """

    file = file_mapping.remote_to_local_file(file)

Теперь ищем места, где наоборот от debug-клиента к Xdebug передаются имена файлов. Таких мест два:
1. Класс Debugger, метод run, заменяем строку
'-t line -f ' + self.breakpt.getfile(bno) + ' -n ' + str(self.breakpt.getline(bno)) + ' -s enabled', \

на
'-t line -f ' + file_mapping.local_to_remote_file(self.breakpt.getfile(bno)) + ' -n ' + str(self.breakpt.getline(bno)) + ' -s enabled', \

2. Класс Debugger, метод mark, заменяем строку:
'-t line -f ' + self.breakpt.getfile(bno) + ' -n ' + str(self.breakpt.getline(bno)), \

на
'-t line -f ' + file_mapping.local_to_remote_file(self.breakpt.getfile(bno)) + ' -n ' + str(self.breakpt.getline(bno)), \


Уже поправленный debugger.py можно взять тут.

Использование


Запускаем отладку

Чтобы начать отладку web-приложения, необходимо запустить vim и нажать <F5>.
Далее, в течение 5 секунд (ниже описано, как увеличить интервал), необходимо запустить какой-либо PHP скрипт, передав GET-ом переменную XDEBUG_SESSION_START со значением 1, например просто открыв соответствующую страницу в браузере, например:
webdev/debug.php?XDEBUG_SESSION_START=1
Альтернативно в php.ini можно задать переменную xdebug.remote_autostart. В таком случае, при запуске любого PHP скрипта, Xdebug будет пытаться подключиться к debug-клиенту.
Подробнее можно прочитать в официальной документации Xdebug.
В итоге должно получиться что-то вроде этого — должен открыться скрипт, который вы запустили:



Окна справа — сверху вниз:
  1. WATCH WINDOW — просмотр контекста
  2. HELP WINDOW — краткое описание возможностей
  3. STACK WINDOW — стек вызова функций
  4. TRACE WINDOW — лог общения debug-клиента c Xdebug, полезно посмотреть если отладка не заработала

Настройка под себя

Таймаут можно задать в том же скрипте, найдя в debugger.py строку:
serv.listen(5) 

и заменив 5 на нужное вам количество секунд.
Комбинации клавиш задаются в debugger.vim, например себе я переназначил <F5> на нажатие «,dr»:
map ,dr :python debugger_run()<cr>
Текст в HELP WINDOW можно поменять в классе HelpWindow, методе on_create.

Навигация по коду

Подробно расписывать не буду, отличия от других отладчиков тут минимальные:
  • Step into (<F2>) — шаг с заходом внутрь функций.
  • Step over (<F3>) — шаг без захода внутрь функций.
  • Step out (<F4>) — выход из функции по стеку вверх.
  • Run (<F5>) — продолжить выполнение до следующего breakpoint.
  • Stack up (:Up) — переход по стеку вверх (смотрите STACK WINDOW).
  • Stack down (:Dn) — переход по стеку вниз (смотрите STACK WINDOW).

Просмотр текущего состояния

  • Property get (<F12>) — получить значение переменной (надо поставить курсор на нужную переменную и нажать <F12>).
  • Context get (<F11>) — получить весь текущий контекст (грубо говоря, все переменные, доступные в данном контексте).
  • Eval (,e) — выполнить произвольное выражение в текущем контексте и получить его значение.

На скриншоте — WATCH WINDOW с выполнеными Context get и Eval:



Установка breakpoints

Toggle breakpoint (:Bp) — установить breakpoint в текущей строке, или удалить, если он уже есть.
На скриншоте — зеленая строка — это строка с breakpoint, красная — это текущая строка:



Resize

Дополнительно по <F1> можно переключатся между двумя режимами — полный, когда показываются различные вспомогательные окна справа, и простым — когда остается только окно с кодом.

Средняя зарплата в IT

120 000 ₽/мес.
Средняя зарплата по всем IT-специализациям на основании 7 154 анкет, за 1-ое пол. 2021 года Узнать свою зарплату
Реклама
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее

Комментарии 31

    0
    Отлично. Сам собирался когда-то поправить неудобство с путями, но руки так и не дошли.
      0
      Я правильно понимаю, что если компьютер разработчика и сервер находятся в разных подсетях, то такие фокусы не пройдут.
        0
        правильно
        и как правило лишние порты всегда прикрыты
        и еще: порт 9000 использует php-fpm
          0
          это решаемая проблема:

          ssh -R 9000:localhost:9000 server.com -l srv_login

          таким образом xDebug будет думать что общается с локальным дебагером, а IDE будет думать что дебажит локальный сервер

          использую это решение с NetBeans + remote xDebug

          –10
          image
            +7
            Сейчас набежит куча линуксоидов, которые вас заминусуют. сам бы сделал но кармы не хватает
            С таким же успехом можно написать «Windows дома. Но зачем?!», «MacOS дома. Но зачем?!», «Android на смартфоне. Но зачем?!», «Мозг в голове. Но зачем?!». Любая аргументация в данном вопросе просто приведет к холивару Linux v.s Windows который всем уже надоел. Каждый использует то, что ему удобно.

              +2
              >Linux дома. Но зачем?
              чтоб максимально приблизить свою среду к среде разработке.
              Если Вы делаете визитки — то Вам это и не надо.
              Если Вы доросли до проекта с нагрузкой от 500 rps, на начинаете задумываться над серверной оптимизацией
                –1
                Фак, меня явно не так поняли. Linux здесь абсолютно не причем. Это была аналогия «удаленная отладка с VIM. Но зачем?» Гораздо удобнее это делать через IDE.
                  0
                  Вы видимо не уловили. Речь идет об отладке не локального кода, а на сервере. А это зачастую нужно, хотя бы потому, что в экстренных ситуациях приходится дебажить за ноутбуком, на котором нет apache etc… где-нибудь в кафе с бесплатным wi-fi (реальная ситуация)
                    –2
                    и? Зачем apache-то в данной ситуации? Я именно так и дебажу, на рабочем компе — windows, на всех серверах — linux и дебаг, и запуск тестов производится именно на удаленном сервере. Да, это немного сложнее настраивается, зато очень и очень удобно.

                    Если Вам приходится часто дебажить код из кафе с ноутбука на котором нету IDE, то наверное стоить задуматься о его установке)
                      +1
                      Вы видимо считаете, что vim нельзя использовать как IDE.
                        0
                        Вы используете его как IDE в повседневной работе? Какие у него преимущества перед теми же phpstorm, netbeans?
                        Я же не говорю, что это плохо или что это нельзя делать. Я пытаюсь понять зачем это нужно, когда есть более удобные средства и для редактирования и для дебага.
                          +1
                          Приимущество? ну это удобно.
                          До этого много чего пробовал, vim(а вернее gvim)оказался самым удобным вариантом. Удобство это весьма субьективно, я знаю больше одного человека, которые спрашивали «Netbeans/eclipse…, а зачем ведь есть вим»
                            0
                            Удобные для кого? Лично для вас? У других людей могут быть свои представления об удобстве.
                            Не думаю, что vim используют только те кто не видел phpstorm/netbeans…
                          0
                          Упал сайт после правки другого программиста. Пришлось заюзать не свой рабочий ноутбук, а то, что было под рукой. Было дико неудобно.
                  0
                  А автору — спасибо за статью, давно мучаюсь с отладкой PHP
                  0
                  Какая-то надуманная проблема. У меня настройка окружения для отладки в пхп сводилась примерно к следующему. Установить xdegug — 1 минута. Установить IDE — 5 минут. Настроить — пару строк в xdebug.ini и пару кликов в IDE. Использовать
                    –1
                    речь ведь идет о удаленном хосте. я лично не видел ниодной IDE котороя нормально дебажет на удоленном хосте, многи это вобще не умеют, большенство просто бер код и запускает в своей среде, а тут именно важно проверить на сервере, с тем пхп что там установлен.

                    если я не прав просветите какая IDE умеет так работать?
                      0
                      PHPStorm очень хорошо дебажит как веб-приложения, так и консольные скрипты. На сайте можно найти мануал как это все настраивается.
                      Веб-приложения можно дебажить в двух режимах:
                      1. активный. когда ты сам нажимаешь кнопку debug, открывается браузер и т.д.
                      2. пассивный. включаешь «listen incoming connections» и IDE будет ловить все запуски и веб-приложения и консольных скриптов.
                        0
                        Шторм все равно будет дебажить ваш локальный код. Сам наступал на эти грабли.
                          0
                          Точнее надо быть уверенным, что один и тот же код лежит локально и на сервере.
                            0
                            Код естественно должен быть одним и тем же. А расположение исходников настраивается в phpStorm аналогичным образом — указывается соответствие локальных путей и удаленных путей, если я не ошибаюсь. С этими же настройками работает deploy.
                        +4
                        Ваша русская языка оченно плохое
                          0
                          Nusphere PHPed тоже справляется с этим на ура. Настраивается все за 10 минут. Причем есть возможность туннелировать запросы через ssh соединение — не важно где находится сервер, главное, чтобы к нему был доступ.
                            0
                            Eclipse замечательно с этим справляется
                          0
                          PHPStorm. У меня схема такая. Линукс сервер на виртуалке. IDE на винде. Дебажиться все бехз проблем ) Один раз там Path mapping настроить надо в IDE и всё
                            +2
                            Статья для Истинных Джедаев, не ищущих лёгких путей?
                              0
                              Ага. пытался сказать тоже самое, только более тонко)
                                0
                                ой, а вы не могли бы выложить свою версию плагина на гитхабе?

                                а так — Спасибо
                                  0
                                  всмысле в репозитории а не в гисте…

                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                Самое читаемое