среда, 21 ноября 2012 г.

Создание дампа базы MySQL в котором используется отдельный INSERT на каждую строку данных

Вчера в процессе прикручивания автоматического создания зон в связке PowerDNS + PowerAdmin мне понадобилось узнать какие данные добавляет PowerAdmin при создании новой зоны. Сперва полез в код, но быстро бросил эту затею.

Следующей мыслью было сравнить дамп базы powerdns до и после создания зоны в poweradmin. Если вы когда-то просматривали дампы, которые по-умолчанию создает mysqldump, то наверняка видели, что там значения в таблицу вставляются через один вызов INSERT. Что-то вроде INSERT INTO `tablename` VALUES (a1, a2, a3, ..., aN), (b1, b2, b3, ..., bN), ...

В итоге таблица где много записей будет выглядеть не информативно при сравнении дампа до и после создания зоны в poweradmin. Чтобы решить эту проблему нужно либо применить "умный" diff, либо заставить mysqldump формировать вставку каждой строки данных через отдельный INSERT.

После пары экспериментов в опциями из man mysqldump нашлась искомая:

$ mysqldump --skip-extended-insert dbname > dbname.sql

При использовании этой опции дамп выглядит так:

INSERT INTO `tablename` VALUES (a1, a2, a3, ..., aN);
INSERT INTO `tablename` VALUES (b1, b2, b3, ..., bN);
...

После этого в выводе diff отлично видно какие данные были добавлены в БД после создания зоны.

понедельник, 19 ноября 2012 г.

Настройка MySQL master-slave репликации

Настраивать master-slave репликацию в MySQL приходится редко, но постоянно приходится подглядывать мануал. Чтобы свести эту операцию к "одному касанию" я добавил этот пост (подходит для Debian-based дистрибутивов, для остальных подойдет если копировать вдумчиво).

Установка MySQL сервера


Устанавливаем MySQL сервер и клиент

# aptitude install mysql-server mysql-client

Далее я убираю удаленный вход в базу под root, тестовую базу и тестового пользователя. Для автоматизации этих действий существует скрипт mysql_secure_installation, входящий в дистрибутив MySQL сервера.

# mysql_secure_installation

Чтобы каждый раз не вводить пароль при подключении к базе я создаю конфиг для консольного клиента

# touch /root/.my.cnf
# chown root:root /root/.my.cnf
# chmod 0600 /root/.my.cnf
# cat > /root/.my.cnf <<EOF
[client]
host=localhost
user=root
password=your-root-password
EOF

Настройка MySQL master ноды


В Debian-based дистрибутивах есть возможность создать локальный конфиг mysql не изменяя /etc/mysql/my.cnf (чтобы не было конфликта при обновлении пакета). Я пользуюсь этой возможностью

# cat > /etc/mysql/conf.d/master.cnf <<EOF
[mysqld]
server-id = 500
log-bin = mysql-bin
log-bin-index = mysql-bin.index
max_binlog_size = 512M
expire_logs_days = 30
bind-address = 0.0.0.0
EOF

# invoke-rc.d mysql restart

При настройке master ноды нужно уделить внимание выбору значения server-id (оно должно быть уникальным в пределах группы серверов, вовлеченных в репликацию). Опции max_binlog_size и expire_logs_days управляют ротацией бинарного лога.

Далее нужно создать пользователя который будет использоваться slave нодами для репликации.

mysql> CREATE USER 'slave-user'@'slave-host' IDENTIFIED BY 'slave-password';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave-user'@'slave-host';
mysql> FLUSH PRIVILEGES;

Далее нужно подготовить слепок баз данных, которые мы будем реплицировать

mysql> FLUSH TABLES WITH READ LOCK;
mysql> SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000004 |     3211 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

Сейчас нужно записать имя файла бинарного лога (mysql-bin.000004) и позицию в этом логе (3211). Далее в этой же сессии выполнить

mysql> \!mysqldump --add-drop-database --all-databases > /tmp/all-db.sql
mysql> UNLOCK TABLES;

Файл /tmp/all-db.sql нужно передать на slave ноду.

Настройка MySQL slave ноды


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

# cat > /etc/mysql/conf.d/slave.cnf <<EOF
[mysqld]
server-id = 510
relay-log = relay-bin
relay-log-index = relay-bin.index
EOF

# invoke-rc.d mysql restart

Далее нужно импортировать файл /tmp/all-db.sql, который был создан на master ноде

# mysql < /tmp/all-db.sql
# mysqladmin flush-privileges

Затем нужно подключить slave ноду к master серверу и запустить репликацию.

mysql> CHANGE MASTER TO master_host='master-host', master_user='slave-user', master_password='slave-password', master_log_file='mysql-bin.000004', master_log_pos=3211;
mysql> START SLAVE;

Посмотреть статус репликации можно командой SHOW SLAVE STATUS\G. Если все работает правильно, то в полях Slave_IO_Running и Slave_IO_Running должно быть значение Yes.

воскресенье, 11 ноября 2012 г.

четверг, 8 ноября 2012 г.

Per-user конфигурация php в WHM/cPanel

SUPHP


Если вы используете suphp в cPanel, то у вас может возникнуть проблема, когда для разных сайтов потребуется различная конфигурация. Из коробки в cPanel конфигурация PHP берется из /usr/local/lib/php.ini. Чтобы создать per-user конфиг нужно:

  • создать файл /home/username/php.ini и добавить в него нужные переопределения относительно общего конфига /usr/local/lib/php.ini. Я туда дописал

    max_execution_time = 7200
  • создать файл /home/username/public_html/.htaccess и добавить в него

    SetEnv PHPRC /home/username/php.ini

Аналогично можно сделать, если иные настройки php нужно сделать не для всех хостов пользователя, а только для одного или нескольких субдоменов. В последнем случае .htaccess нужно положить в соответствующем docroot'е.

CGI/FastCGI


Если на сервере PHP работает в режиме CGI/FastCGI, то начиная с PHP 5.3.0 появилась поддержка INI-файлов в стиле .htaccess на уровне каталога. Для изменения параметров интерпретатора нужно:

  • создать файл .user.ini (имя файла зависит от значения параметра user_ini.filename) в docroot'e сайта.

    xdebug.remote_enable = On
    xdebug.remote_host = 192.168.1.115
    xdebug.remote_port = 9000
    xdebug.remote_mode = req
  • подождать пока истечет период обновления (зависит от значения user_ini.cache_ttl) или перезагрузить веб-сервер.

вторник, 6 ноября 2012 г.

[ipcheck] Problem with DNS setup on cpanel

Дошли руки разобраться с письмами "которые нельзя игнорировать", которыми спамит свежеустановленная WHM/cPanel. Письма выглядят так:

Subject: [ipcheck] Problem with DNS setup on cpanel

IMPORTANT: Do not ignore this email.

Your hostname (cpanel) could not be resolved to an IP address. This
means that /etc/hosts is not set up correctly, and/or there is no
dns entry for cpanel. Please be sure that the contents of
/etc/hosts are configured correctly, and also that there is a
correct 'A' entry for the domain in the zone file.
Some or all of these problems can be caused by /etc/resolv.conf
being setup incorrectly. Please check that file if you believe
everything else is correct.

You may be able to automatically correct this problem by using the
'Add an A entry for your hostname' option under 'Dns Functions' in
your Web Host Manager.

Суть письма сводится к тому, что скрипт /scripts/ipcheck не может выполнить преобразование hostname в ipaddress. Данный экземпляр cPanel крутится в CentOS 6.x контейнере под управлением OpenVZ.

Сначала появилась мысль, что слетел hostname. Проверил догадку:

# hostname
cpanel

# hostname --fqdn
cpanel.srv.example.com

# dnsdomainname.
srv.example.com

# hostname -i
1.2.3.4

На первый взгляд все правильно. Полез в сам скрипт, чтобы узнать как выполняется преобразование. Из кода видно, что скрипт пытается получить ip для $hostname = Cpanel::Sys::Hostname::gethostname() и судя по письму $hostname равен "cpanel", а не "cpanel.srv.example.com". Т.е. выполняется gethostbyname($hostname).

Чтобы исправить эту ситуацию достаточно подкрутить резолвер (правильно установить параметр search в /etc/resolv.conf). В случае с контейнером OpenVZ это выглядит так:

# vzctl set 300 --searchdomain srv.example.com

Осталось проверить правильность новых настроек, запустив /scripts/ipcheck, если все в порядке, то скрипт не вернет никакого вывода.

четверг, 1 ноября 2012 г.

Wacom Intuos GD-0608-R в Windows XP

Позавчера битый час пытался заставить работать старенький планшет Wacom Intuos GD-0608-R (подключается через последовательный порт). На новом компе нашего дизайнера не нашлось COM-порта, выведенного на заднюю панель, так что сначала пришлось откопать в завалах старого барахла подходящую планку с подключением к колодке на материнской плате.

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

Сегодня пришел пораньше и устроил забег по поисковику. В результате откопал пост в котором человек описывает запуск этого планшета под Windows Vista. Если вкратце то планшет заработал после этих действий:
  1. После подключения планшета откажитесь от установки драйверов в Windows;
  2. Скачайте драйвер с сайта Wacom (я пробовал самый свежий, но похоже новые драйвера  не поддерживают эту модель);
  3. Создайте ветку в реестре [HKEY_LOCAL_MACHINE\SOFTWARE\Tablet](если ее еще там нет) и добавить в нее строковый параметр "PnPTablets"=",COM1". Если у вас последовательный порт, к которому подключен планшет, имеет другое название, то замените COM1 на ваше значение;
  4. Установите драйвер. Планшет должен начать работать сразу после завершения установки драйвера.
Теперь планшет работает исправно.

Анимированный GIF для индикации выполнения запроса

Сегодня искал анимированный GIF, чтобы организовать индикацию выполнения действий. На глаза попался сайт, где есть неплохой выбор - www.loadinfo.net. Все иконки, сгенерированные этим сайтом, заявлены как бесплатные. Лично мне приглянулась самая первая из них.