Pull to refresh

PHPStorm + XDebug + Bitbucket: разработка на удаленном сервере в небольшой команде

Reading time 6 min
Views 34K
В этой статье я расскажу как мы построили процесс разработки сайта не поднимая локальных копий веб-сервера в небольшой команде разработчиков с использованием Xdebug на тестовом сервере и автоматического развертывания репозитория на боевой сервер.



Немного о причинах НЕ поднимать локальную копию веб-сервера:
  1. Если вы работаете под Windows, а веб-сервер на линукс, то локальный сервер для сложного портала(в котором много специфического софта) под винду поднять бывает вообще невозможно, остается поднимать копию на виртуальной машине, но в этом случае разница в настройке ПО разработчика между настройкой под виртуальную машину и настройкой под удаленный веб-сервер заключается лишь в IP адресе.
  2. Если таки поднимать локальную копию, то придется постоянно синхронизировать настройки ПО сервера, базу данных и кроме того остается вопрос как быть с крон-задачами, которые часто должны выполняться под утро.
  3. Если сайт распологается на нескольких серверах или даже отдельные его части занимают несколько серверов(например, масштабированные таблицы — часть таблицы на одном, часть на другом сервере), то все это тоже может сильно усложнить задачу создания локального сервера.
  4. Производительность вашей машины и сервера может сильно различаться, что может иметь влияние и на код.
  5. Далеко не все участники проекта могут распологать достаточными навыками системного администрирования.

Но отказываясь от создания локальной копии сервера, мы теряем массу плюсов такого подхода:
  1. Запуск интерпретатора из IDE и соответственно отладка.
  2. Скорость закачки файлов и пинг.
  3. Разработчики работают каждый со своей копией сервера, поэтому они друг другу никак не могут помешать.

Если отладку можно получить с помощью Xdebug, а скорость переехав на другой сервер, то третье преимущество может стать серьезной помехой, поэтому моя статья актуальна в первую очередь небольшим командам, где можно давать задачи т.о. чтобы они практически не пересекались между собой.

Есть еще один вариант организации серверов разработки — каждому участнику проекта создается своя копия файлов и домены на сервере, т.о. сервер один, причем удаленный, но при этом каждый разработчик не мешает другому… минус такого подхода в высокой сложности организации, особенно если у проекта много поддоменов.

Пояснения к схеме:

  • Разработчик имеет копию репозитория
  • Тестовый и боевой веб-сервер в качестве корневой директории проекта имеет рабочую копию репозитория
  • Файлы проекта связаны в PHPStorm с рабочей директорией тестового веб-сервера, это значит при Ctrl+S происходит автоматический аплод редактируемого файла на сервер

Как происходит разработка:

  1. разработчик правит код локально
  2. нажимает Ctrl+S файл загружается на сервер
  3. запускает в браузере нужную станицу тестового веб-сервера(или выполняет на ней нужное действие), смотрит результат
  4. если необходимо запускает дебаггер с помощью Xdebug
  5. если все устраивает делает коммиты в репозиторий и потом Push
  6. хранилище(в нашем случае это Bitbucket) автоматически после каждого Push'а опрашивает указанный скрипт на боевом сервере
  7. при опросе этот скрипт вызывает git pull и т.о. приводит рабочую директорию боевого веб-сервера до актуальной версии из репозитория

Подготовка сервера

в нашем случае проект существовал без репозитория, отдельная тема как его туда добавить(т.к. надо исключить массу файлов которые не нужно добавлять в репу), но допустим репа уже есть на Bitbucket, а файлы на сервере лежат в обычной директории
  1. логинимся под юзером проекта:
    su myproject
    
  2. генерим SSH ключи для авторизации на bitbucket без пароля
    ssh-keygen -t rsa
    
  3. получаем публичный ключ
    cat ~/.ssh/id_rsa.pub
    и добавляем его на Bitbucket в раздел Deployment keys в настройках проекта
  4. клонируем проект во временную директорию ~/tmp/myproject.ru:
    mkdir ~/tmp
    mkdir ~/tmp/myproject.ru
    cd ~/tmp/myproject.ru
    git clone git@bitbucket.org:username/myproject.ru.git
    
  5. копируем .git и .gitignore в рабочую директорию проекта (у нас это /vhosts/myproject.ru/), остальные файлы не копируем!
    cp -r .git .gitignore /vhosts/myproject.ru/
    rm -rf ~/tmp/myproject.ru
    
  6. приводим файлы к состоянию из репозитория
    cd /vhosts/myproject.ru
    git reset --hard
    

Подготовка клиента

Если у вас еще не установлен Git — ставим
В PHPStorm прописываем путь до Git'а (это файл bin/git.exe) — Settings -> Version Control -> Git -> Path to Git executable

Клонируем репозиторий:

В PHPStorm вкладка VSC -> Checkout from Version Control -> Git
указываем имя новой директории проекта и путь к репозиторию, например
username@bitbucket.org/username/myproject.ru.git

Сихноризируем файлы с удаленным сервером:

  1. Добавляем сервер и указываем его доступы File -> Settings -> Deployment
  2. в Root path указываем путь до корня проекта (в моем случае /vhosts/myprojet.ru/) — корень проекта на сервере должен совпадать по иерархии файлов с корневой директорией репозитория
  3. Переходим во вкладку Mappings и указываем в Deployment path on server — / и в Web path on server тоже — / (если тот начинается с корня сайта)
  4. Выбираем наш сервер в списке и жмем на кнопку Use as default
  5. Далее в Deployment -> Options нужно выбрать On explicit save action (Ctrl+S) в Upload changed files automatically to the default server
  6. В Warn when uploading over newer file выбираем Compare timestamp & size (хотя можно и по содержимому) и отмечаем Notify about remote changes, это позволит узнать если кто-то правил тот же файл

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

Настройка автопула на боевом сервере:

  1. Создаем shell скрипт для автоматического pull'а проекта /vhosts/myproject.ru/gitsync.sh:
    #!/bin/sh
    cd /vhosts/myproject.ru && git reset --hard && git status --porcelain -uall | egrep '^\?\?' | awk '{ print $2; }' | xargs rm && git pull
    Поскольку git выдает ошибку при pull, если добавлены новые файлы, но при этом не зафиксированы, а git reset --hard их не удаляет, то мы парсим вывод git status и удаляем новые файлы, чтобы они были загружены из репозитория, кроме того git reset --hard отменяет все изменения в файлах, чтобы не было конфликтов.
    Не забываем добавить права на исполнение скрипту
    chmod a+x /vhosts/myproject.ru/gitsync.sh
    
  2. Поскольку операции с репозиторием проходят от пользователя-владельца файлов, а веб-сервер работает от другого пользователя, то нужно ему добавить разрешение на запуск авто-pull скрипта от чужого имени без пароля через /etc/sudoers
    # /etc/sudoers
    #
    # This file MUST be edited with the 'visudo' command as root.
    #
    # See the man page for details on how to write a sudoers file.
    #
    Defaults        env_reset
    #Чтобы можно было выполнять sudo без терминала, т.е. прямо от веб-сервера
    Defaults:www-data !requiretty
    # Host alias specification
    
    # User alias specification
    
    # Cmnd alias specification
    
    # User privilege specification
    root    ALL=(ALL) ALL
    
    # Allow members of group sudo to execute any command
    # (Note that later entries override this, so you might need to move
    # it further down)
    %sudo ALL=(ALL) ALL
    #
    #includedir /etc/sudoers.d
    
    #разрешаем запуск скрипта от чужого имени без пароля
    www-data ALL = (myproject) NOPASSWD: /vhosts/myproject.ru/gitsync.sh
    
  3. Созадем php скрипт, который будет из веба запускать наш shell скрипт /vhosts/myproject.ru/htdocs/gitsync.php (название можно выбрать более секретное, как и добавить передачу пароля):
    <?php
        $output = array();
        exec('sudo -u myproject /vhosts/myproject.ru/gitsync.sh 2>&1', $output);
        foreach ($output as $line)
        {
            echo $line."\r\n";
        }
        die();
    ?>
    
  4. в Bitbucket в настройках проекта во вкладке Services в раздел POST пишем путь до скрипта автопула: myproject.ru/gitsync.php и жмем Save

Теперь после каждого push'а все файлы на сервере будут приводится к файлам из репозитория, можно такой же подход реализовать и на тест сервере, но в этом случае если один разработчик имеет незапушеные файлы, то на сервере они затрутся и их придется заново загружать.

Подключаем Xdebug

Как установить его не буду описывать, будем считать что Xdebug установлен, правим конфиг /etc/php5/conf.d/xdebug.ini:
zend_extension=/usr/lib/php5/20090626/xdebug.so
xdebug.remote_enable=1
xdebug.remote_connect_back=1
xdebug.idekey=PHPSTORM
xdebug.remote_port=9000

Обратите внимание на директиву remote_connect_back — она позволяет коннектиться не к заданному IP машины разработчика, а к IP клиента который находится в окружении PHP (REMOTE_ADDR), т.о. с Xdebug могут работать одновременно несколько человек. Это не значит что Xdebug будет запущен при каждом обращении к серверу, для его старта по прежнему требуется передать определенные cookies — подробнее

Вбиваем тут IDE key указанный нами в xdebug.idekey ключ PHPSTORM и появившиеся ссылки внизу перестакиваем на панель закладок

Настраивать в PHPStorm специально ничего не надо, все уже настроено, но на всякий случай настройки тут — Project Settings -> PHP -> Debug

теперь чтобы отладчик заработал нужно:
  1. в PHPStorm включить прослушку коннектов дебаггеров — кнопка Start Listen PHP Debug Connection
  2. открыть сайт, ткнуть закладку Start debugger, перезагрузить страницу
  3. PHPStorm должен маякнуть о входящем подключении и открыть дебаггер

Поскольку соединение идет из вне, а многие теперь сидят за роутерами, то на роутере нужно сделать проброс порта 9000 на ваш локальный IP адрес, на D-link DIR 300 это выглядит примерно так:

Если debugger выдает ошибку, что не может найти соответствующий текущий исполняемый файл на локальной машине, то в настройках PHP -> Servers можно задать соответствие путей на сервере путям на локале.

Ссылки:
http://git-scm.com/
http://xdebug.org/
http://bitbucket.org/
http://jetbrains.com/phpstorm/
Tags:
Hubs:
+20
Comments 67
Comments Comments 67

Articles