Грабельки deployment при наличии opcode кэша

Привет, PHP разработчик, администратор или релиз-менеджер! Наткнулся на интересное, спешу поделиться.

Дано:

Проект на PHP, одновременно работающий в режиме разработки («DEV», из SVN), а также боевом режиме («LIVE»), в который переводится ветка DEV после отлова багов. Сервер примечателен только тем, что PHP запускается через php-fpm и там включено opcode кэширование. У меня нижеследующее проявилось и при XCache и при APC.

Надо:

Перевести отлаженный проект из режима разработки в режим работы.

Решаем:

Итак, имеем примерно такую структуру проекта (ненужное вырезано):

.../dev/
       /app/
           /index.php : <?php require dirname(__FILE__).'/../conf.php'; print $me;
       conf.php       : <?php $me = 'dev';
.../live/
       /app/
           /index.php : <?php require dirname(__FILE__).'/../conf.php'; print $me;
       conf.php       : <?php $me = 'live';

Два виртуальных хоста в web сервере берут данные из …/dev/ и …/live/, где лежит соответствующий код. Всё работает, opcode кэш ускорят работу, все счастливы. Запрос на …/dev/app/index.php возвращает «dev», на …/live/app/index.php — «live».

Но вот пришла пора выложить код из DEV в LIVE как можно более быстро и без глюков. Понятно, что вариантов море, один из пришедших в голову был таков: для deployment использовать 2 команды переименования каталогов. Это на самом деле весьма «дешево»: операционная система сделает очень мало работы в очень короткое время, сбои крайне маловероятны:

mv .../live/app .../bak && mv .../dev/app .../live

И вот в очень короткое время мы переместили код. Всё хорошо? Нет! Запрос на …/live/app/index.php возвращает «dev», сайт работает с тестовыми данными разработчика! 🙁

Расследование:

Собственно, поиск причины был не сильно долгим. Мы переместили ветку файловой системы, идентификаторы файлов («inode») внутри ветки не поменялись и op-кэш наивно думает, что ничего не поменялось, т.к. он идентифицирует код по идентификатору файла. Ну и в итоге в окружении LIVE лежит файл, который запускается интерпретатором PHP со включенным файлом конфигурации на момент попадания в кэш — это был файл из DEV ветки. Вот так.

Итого мораль — при переносе дерева файлов PHP в рамках обработчика PHP с включенным opcode кэшированием вы продолжаете использовать старый закэшированный код, даже если включенные из перенесенных файлы поменялись.

Что делать?

Один из вариантов, и как мне кажется правильный — это запустить два экземпляра php-fpm обработчика. Отдельно для DEV и LIVE окружений. Или полностью исключить некоторые файлы из кэширования.

Комментариев нет »10.02.2012 12:38:48 | Делаю | , ,

Русский в консоли Ubuntu Server

В Ubuntu в очередной раз поломали отображение национальных шрифтов в консоли (именно в консоли, а не в эмуляторе терминала). Я, помнится, около 2008 года уже помог починить, но «технологии шагнули далеко вперед» 🙂

Что случилось и как починить — читайте в статье: http://help.ubuntu.ru/wiki/russian_font_in_console.

Приводить полностью не буду, если кратко, то надо добавить FRAMEBUFFER=Y в /etc/initramfs-tools/initramfs.conf и после перенастройки консоль будет оставаться правильно настроенной при перезагрузке.

 

Это реклама Русскоязычной пользовательской документации Ubuntu, в составлении которой можно и нужно поучаствовать, если вы владеете информацией и хотите поделиться с людьми.

комментария 2 »08.02.2012 08:42:58 | Ubuntu | ,

Репликация MySQL на одном сервере

Привет, администраторы!

Попалась любопытная задача, сделать репликацию одной базы в другую на том же самом сервере. Решение нашлось.  Забавное. Привожу дополнено и по-русски:

Дано:

MySQL сервер (у меня он на Ubuntu, но тут, пожалуй не важно) — одна штука, база данных base1.

Надо:

Сделать репликацию базы на том же самом сервере, не запуская дополнительных процессов, в базу base2.

Решение:

Копируем base1 в base2, каким угодно способом, это ваше начальное состояние, после этого base1 не должна меняться.

Настраиваем [mysql] секцию в /etc/mysql/my.cnf, добавив:

...
server-id=1
report-host=master-is-slave-host
log-bin=myserver-binlog
relay-log=myserver-relaylog
replicate-same-server-id=1
binlog-do-db=base1
replicate-rewrite-db=base1->base2
replicate-do-db=base2
...

После этого следует перезапустить сервер и можно увидеть, что binlog начал писаться:

# service mysql restart
...
# ls /var/lib/mysql/myserver*
myserver-binlog.000001

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

Осталось запустить репликацию, выполняем админом в базе:

GRANT REPLICATION SLAVE ON *.* TO 'repl'@'localhost' IDENTIFIED BY 'CoolPassW0rd';
FLUSH PRIVILEGES;
CHANGE MASTER TO MASTER_HOST='localhost', MASTER_USER='repl',
    MASTER_PASSWORD='CoolPassW0rd', MASTER_LOG_FILE='myserver-binlog.000001';
START SLAVE;

И для контроля, что всё ок, посмотрите, что выдают:

SHOW MASTER STATUS;
SHOW SLAVE STATUS;

Типа всё. Согласен получить комментарии по теме!

комментария 2 »07.02.2012 17:58:30 | Ubuntu, Делаю | , ,

Python beginners class from Google

Just watched Google python class done by Nick Parlante. It is rather introductory but very useful and cool.

Here is the class homepage.

Lecture videos:

1.1 Introduction, strings
1.2 Lists and sorting
1.3 Dicts and files
2.1 Regular expr
2.2 Utilities
2.3 Utilities urllib
2.4 Conclusions

Комментариев нет »04.02.2012 13:18:10 | English |