MySQL ZFS Backup v2

Обновил и расширил функциональность своего скрипта, осуществляющего бэкап базы данных MySQL с помощью ZFS снапшотов.

Новая версия умеет понимать параметры, передаваемые из командной строки, умеет работать с файлом конфигурации и обрабатывать несколько датасетов за раз. Типичный пример использования скрипта mysql_zfs_backup.sh:

db# ./mysql_zfs_backup.sh -u mysqluser -p mysqlpass -d rpool/mysql -d ssd/mysql
Replication is running: 0 seconds master delay
Snapshots will be rotated for ZFS datasets: rpool/mysql ssd/mysql
Done

Конфигурация по-умолчанию читается из файла mysql_zfs_backup.conf:

mysql_user='mysqluser'
mysql_pass='mysqlpass'
zfs_datasets='rpool/mysql ssd/mysql'
quiet='0'

И, кстати:

db# /bin/sh -c 'time -h ./mysql_zfs_backup.sh'
Replication is running: 0 seconds master delay
Snapshots will be rotated for ZFS datasets: rpool/mysql
Done
        3.09s real              0.02s user              0.00s sys
db# du -h -c /var/db/mysql | grep total
 79G    total

Файлы: сам скрипт, пример конфига.

Обновляем базу дисков smartmontools

При использовании Super Talent UltraDrive ME SSD FTM28GX25H возникли жуткие, на первый взгляд, проблемы:

Jul  6 10:09:20 srv3 smartd[1189]: Device: /dev/ada0, 40699 Offline uncorrectable sectors (changed +111)
Jul  6 10:39:21 srv3 smartd[1189]: Device: /dev/ada0, 40801 Offline uncorrectable sectors (changed +102)
Jul  6 11:09:21 srv3 smartd[1189]: Device: /dev/ada0, 40893 Offline uncorrectable sectors (changed +92)
Jul  6 11:39:20 srv3 smartd[1189]: Device: /dev/ada0, 40999 Offline uncorrectable sectors (changed +106)
Jul  6 12:09:20 srv3 smartd[1189]: Device: /dev/ada0, 41095 Offline uncorrectable sectors (changed +96)
Jul  6 12:39:20 srv3 smartd[1189]: Device: /dev/ada0, 41184 Offline uncorrectable sectors (changed +89) 

При этом диск отсутствовал в базе дисков smartmontools:

=== START OF INFORMATION SECTION ===
Device Model:     STT_FTM28GX25H
Serial Number:    P604790-AFBX-C289057
Firmware Version: 1916
User Capacity:    128,035,676,160 bytes
Device is:        Not in smartctl database [for details use: -P showall]

Проблема решилась как всегда просто и элегантно:

fetch -o /usr/local/share/smartmontools/drivedb.h "http://sourceforge.net/apps/trac/smartmontools/browser/branches/RELEASE_5_39_DRIVEDB/smartmontools/drivedb.h?format=txt"

Результат не заставил себя ждать:

=== START OF INFORMATION SECTION ===
Model Family:     SuperTalent UltraDrive GX SSD
Device Model:     STT_FTM28GX25H
Serial Number:    P604790-AFBX-C289057
Firmware Version: 1916
User Capacity:    128,035,676,160 bytes
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate     0x0000   ---   ---   ---    Old_age   Offline      -       6
  9 Power_On_Hours          0x0000   ---   ---   ---    Old_age   Offline      -       896
 12 Power_Cycle_Count       0x0000   ---   ---   ---    Old_age   Offline      -       1
184 Initial_Bad_Block_Count 0x0000   ---   ---   ---    Old_age   Offline      -       26
195 Program_Failure_Blk_Ct  0x0000   ---   ---   ---    Old_age   Offline      -       0
196 Erase_Failure_Blk_Ct    0x0000   ---   ---   ---    Old_age   Offline      -       0
197 Read_Failure_Blk_Ct     0x0000   ---   ---   ---    Old_age   Offline      -       0
198 Read_Sectors_Tot_Ct     0x0000   ---   ---   ---    Old_age   Offline      -       2799845469
199 Write_Sectors_Tot_Ct    0x0000   ---   ---   ---    Old_age   Offline      -       967040916
200 Read_Commands_Tot_Ct    0x0000   ---   ---   ---    Old_age   Offline      -       21971239
201 Write_Commands_Tot_Ct   0x0000   ---   ---   ---    Old_age   Offline      -       12340096
202 Error_Bits_Flash_Tot_Ct 0x0000   ---   ---   ---    Old_age   Offline      -       2538957
203 Corr_Read_Errors_Tot_Ct 0x0000   ---   ---   ---    Old_age   Offline      -       2200648
204 Bad_Block_Full_Flag     0x0000   ---   ---   ---    Old_age   Offline      -       0
205 Max_PE_Count_Spec       0x0000   ---   ---   ---    Old_age   Offline      -       10000
206 Min_Erase_Count         0x0000   ---   ---   ---    Old_age   Offline      -       4
207 Max_Erase_Count         0x0000   ---   ---   ---    Old_age   Offline      -       359
208 Average_Erase_Count     0x0000   ---   ---   ---    Old_age   Offline      -       102
209 Remaining_Lifetime_Perc 0x0000   ---   ---   ---    Old_age   Offline      -       99
211 Unknown_Attribute       0x0000   ---   ---   ---    Old_age   Offline      -       0
212 Unknown_Attribute       0x0000   ---   ---   ---    Old_age   Offline      -       0
213 Unknown_Attribute       0x0000   ---   ---   ---    Old_age   Offline      -       0

Жуткие счетчики Offline uncorrectable sectors на деле оказались обычными счетчиками операций чтения/записи.

Пускаем redmine в nginx с помощью passenger модуля

Ура! В кои веки нашел нормальный таск менеджер и трекер времени — redmine.
Он хоть и хоть и написан на богомерзком руби, но работает шустро и локализован просто отлично.
В портах его можно найти в /usr/ports/www/redmine

Первоначальная настройка подробна описана в вики на сайте проекта.
Из подводных камней столкнулся лишь с не работающими из коробки уведомлениями по email, проблема решилась весьма быстро:

config/email.yml:

production:
  delivery_method: :smtp
  smtp_settings:
    tls: true
    enable_starttls_auto: true
    address: "smtp.gmail.com"
    port: '587'
    domain: "smtp.gmail.com"
    authentication: :plain
    user_name: "foo@gmail.com"
    password: "bar"

Научить nginx работать с redmine тоже очень просто. Достаточно собрать nginx с модулем passenger и настроить конфигурацию следующим образом:

В секции http описываем глобальные настройки passenger:

passenger_root /usr/local/lib/ruby/gems/1.8/gems/passenger-2.2.15;
passenger_ruby /usr/local/bin/ruby;

И добавим сервер, который будет обрабатывать к redmine:

server
{
    listen 1.2.3.4:80;
    server_name redmine.domain.tld;
    charset utf-8;
    passenger_enabled on;
    root /usr/local/www/redmine/public;
}

Патч, добавляющий поддержку php-fpm в порт lang/php5

Набросал небольшой патч, добавляющий в порт php 5.3 поддержку php-fpm. Из недостатков — требует наличие svn клиента для загрузки патчей с репозитария svn.php.net. Зато в теории будет работать для любой стабильной версии порта в пределах ветки 5.3.x.

Установка очень простая:

cd /usr/ports/lang/php5
fetch http://sav.ecom24.ru/freebsd/fpm.patch
patch < fpm.patch
make config install clean

Сам патч:

--- Makefile    2010-06-17 07:59:24.414207380 +0000
+++ Makefile    2010-06-17 08:56:48.418613806 +0000
@@ -43,7 +43,8 @@ OPTIONS=      CLI "Build CLI version" on \
                SUHOSIN "Enable Suhosin protection system" on \
                MULTIBYTE "Enable zend multibyte support" off \
                IPV6 "Enable ipv6 support" on \
-               MAILHEAD "Enable mail header patch" off
+               MAILHEAD "Enable mail header patch" off \
+               FPM "Enable PHP-FPM patch" off

 CONFLICTS=     php4-4* php5-pcre-* php5-spl-*

@@ -51,6 +52,13 @@ MAN1=                php-config.1 phpize.1

 .include 

+.if defined(WITH_FPM)
+USE_RC_SUBR=   php-fpm.sh
+LIB_DEPENDS+=  event:${PORTSDIR}/devel/libevent
+BUILD_DEPENDS+=        svn:$(PORTSDIR)/devel/subversion
+CONFIGURE_ARGS+=--enable-fpm --with-fpm-log=/var/log/php-fpm.log --with-fpm-pid=/var/run/php-fpm.pid
+.endif
+
 PATCH_DIST_STRIP=      -p1

 .if !defined(WITHOUT_SUHOSIN)
@@ -136,9 +144,16 @@ CONFIGURE_ARGS+=--disable-ipv6
 post-patch:
        @${TOUCH} ${WRKSRC}/ext/php_config.h
        @${REINPLACE_CMD} "s|^\(extension_dir\)|; \1|" ${WRKSRC}/php.ini-*
+       @(svn export http://svn.php.net/repository/php/php-src/branches/PHP_5_3/sapi/fpm ${WRKSRC}/sapi/fpm)

 pre-configure:
        @${CAT} ${WRKSRC}/acinclude.m4 ${WRKSRC}/build/libtool.m4 > ${WRKSRC}/aclocal.m4
+       @(cd ${WRKSRC} && ./buildconf --force)
+
+post-configure:
+.if defined(WITH_FPM)
+       @${REINPLACE_CMD} "s|/usr/local/var|/var|" ${WRKSRC}/sapi/fpm/php-fpm.conf
+.endif

 post-build:
        @${ECHO_CMD} "PHP_VER=5" > ${WRKDIR}/php.conf
--- files/php-fpm.sh.in 1970-01-01 00:00:00.000000000 +0000
+++ files/php-fpm.sh.in 2010-06-17 09:05:07.600963518 +0000
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+# PROVIDE: php-fpm
+# REQUIRE: NETWORKING SERVERS
+# KEYWORD: shutdown
+
+# Add the following lines to /etc/rc.conf to enable php-fpm:
+# php_fpm_enable (bool):      Set to "NO" by default.
+#                             Set it to "YES" to enable php-fpm
+# php_fpm_config (str):       Set to "" by default.
+#                             Define your php-fpm configuration file here.
+
+. /etc/rc.subr
+
+name="php_fpm"
+rcvar=`set_rcvar`
+
+load_rc_config $name
+
+: ${php_fpm_enable="NO"}
+: ${php_fpm_pidfile="/var/run/php-fpm.pid"}
+: ${php_fpm_config="%%PREFIX%%/etc/php-fpm.conf"}
+
+command="%%PREFIX%%/sbin/php-fpm"
+pidfile=${php_fpm_pidfile}
+reload_precmd="php_fpm_prereload"
+quit_cmd="php_fpm_quit"
+
+[ -n "$php_fpm_config" ] && php_fpm_flags="--fpm-config $php_fpm_config"
+
+php_fpm_prereload()
+{
+       sig_reload=USR2
+}
+
+php_fpm_quit()
+{
+       sig_stop=QUIT
+       run_rc_command stop
+}
+
+extra_commands="reload quit"
+run_rc_command "$1"

Сдох SSD

Внезапно сдох 128 гиговый ссд диск STT FTM28GX25H 1916. Проработал недели три в качестве log/l2arc для zfs пула.

ahcich0: Timeout on slot 31
ahcich0: Timeout on slot 31
ahcich0: Timeout on slot 31
ahcich0: Timeout on slot 31
(ada0:ahcich0:0:0:0): lost device

Похерился пул вместе с данными. Благо бэкапный мастер под боком был. Мораль — используйте для лог девайсов зеркало!

Организация горячего кэширования статики в nginx

В определенных ситуациях требуется быстро раздавать фиксированный набор статических файлов, например при раздаче swf файлов flash/flex приложений.
Для того, чтобы снизить нагрузку на диски и уменьшить время реакции, можно организовать горячее кэширование файлов в оперативной памяти:

Создадим хранилище для кэша на md диске:

mkdir /var/tmp/nginx
chown www:www /var/tmp/nginx
echo "md /var/tmp/nginx mfs rw,-s128m,late 2 0" >> /etc/fstab
mount /var/tmp/nginx

Организуем локальный сервер для раздачи статики, с которого будет заполняться кэш:

server
{
    listen 127.0.0.1:80;
    root /usr/local/www/site;
}

В контексте http описываем зону кэширования:

proxy_cache_path /var/tmp/nginx/store levels=1:2 keys_zone=STATIC:10m inactive=1d max_size=128m;

В контексте server добавляем location для статики, которую будем кэшировать:

location ~\.swf$ {
    proxy_pass http://127.0.0.1:80;
    expires 30d;
    proxy_intercept_errors on;
    proxy_cache STATIC;
    proxy_cache_min_uses 1;
    proxy_cache_valid 1d;
    proxy_ignore_client_abort on;
    proxy_temp_path /var/tmp/nginx/tmp;
    proxy_cache_use_stale updating;
}

Перегружаем сервер и запрашиваемые swf файлы начинают кэшироваться на md диске:

/usr/local/etc/rc.d/nginx reload

Смотрим количество трансляций в ipfw nat

Добавляем параметр log к конфигурации ната:

ipfw nat 1 config ip 1.2.3.4 log

Теперь количество трансляций можно посмотреть командой:

# ipfw nat show
nat 1: icmp=106, udp=34388, tcp=115736, pptp=0, proto=0, frag_id=14 frag_ptr=0 / tot=150244

Есть возможность посмотреть, сколько ядерной памяти потребляет нат:

# vmstat -m | grep alias | tr -s ' ' | cut -d ' ' -f 4
33311K

Фильтрация µTP (Micro Transport Protocol) во FreeBSD, используя ng_ipfw и ng_bpf

В связи с тем, что в новой версии популярного торрент клиента µTorrent была включена поддержка протокола µTP, значительно выросло количество транзитных пакетов на пограничных маршрутизаторах. Было принято решения заблокировать паразитный трафик.

#!/bin/sh
/usr/sbin/ngctl mkpeer ipfw: bpf 2 main

/usr/sbin/ngctl name ipfw:2 utp_filter
/usr/sbin/ngctl msg utp_filter: setprogram { thisHook=\"main\" ifMatch=\"\" ifNotMatch=\"main\" bpf_prog_len=12 bpf_prog=[ { code=48 jt=0 jf=0 k=0 } { code=84 jt=0 jf=0 k=240 } { code=21 jt=0 jf=8 k=64 } { code=48 jt=0 jf=0 k=9 } { code=21 jt=0 jf=6 k=17 } { code=40 jt=0 jf=0 k=6 } { code=69 jt=4 jf=0 k=8191 } { code=177 jt=0 jf=0 k=0 } { code=64 jt=0 jf=0 k=20 } { code=21 jt=0 jf=1 k=2147483647 } { code=6 jt=0 jf=0 k=65535 } { code=6 jt=0 jf=0 k=0 } ] }

/sbin/ipfw add 2 netgraph 2 udp from any to any iplen 0-128

Описание протокола в Wikipedia
Оригинал записи на nag.ru

Как подружить natd и mpd5 в режиме клиента

При использовании mpd5 в качестве клиента часто сталкиваюсь с необходимостью завернуть весь трафик через ng интерфейс в нат. Делается это очень просто — с помощью up- и down-скриптов, которые вызываются, когда интерфейс создается и удаляется. Добавляем в mpd.conf строчки

set iface up-script /usr/local/etc/mpd5/iface-up.sh
set iface down-script /usr/local/etc/mpd5/iface-down.sh

И создаем соответствующие скрипты:

#!/bin/sh
route delete default
route add default $4
natd -n $1 -s -dynamic -P /var/run/natd-$1.pid
ipfw delete 10000
ipfw add 10000 divert natd all from any to any via $1
#!/bin/sh
route delete default
kill `cat "/var/run/natd-$1.pid"`
ipfw delete 10000

Please welcome HAST — Highly Avalable Storage

Тем временем Pawel Jakub Dawidek влил в HEAD код HAST (Highly Avalable STorage), геом класс, позволяющий организовывать зеркало из дисков, расположенных на разных серверах. Синхронизация такого хранилища будет осуществляться по TCP/IP. Функциональность обещает быть схожей с линуксовым DRDB.

Оригинальное сообщение в рассылке
Описание во FreeBSD WIKI