FastNetMon

Thursday, 17 April 2014

librsync и утилита rdiff - все что Вы НЕ знали о резервном копировании

Данный пакет утилит крайне полезен. Чем? В первую очередь, очень высоким в отличие от rsync уровнем контроля за тем, что же делается :)

Вот, например, мы можем взять 8 гигабайтный бинарный файл (созданный из данных за 8е апреля) и сгенерировать для него signature файл вот так:
time rdiff signature 56640_root_hdd.gz_84cab040-bed0-11e3-b5aa-80259087d80c /root/56640.signature

real    0m42.922s
user    0m34.305s
sys     0m2.209s

Займет он при этом 47 мегабайт всего-то. Что такое signature файл? Грубо говоря, это файл с полной информацией о блоках данного файла и их хэш суммах. Для чего это может понадобится? Об этом позже.

Итак, допустим у нас есть актуальная (за 18е апреля) копия данного файла (это НЕ архив, это просто большой файл с бинарными данными).

Итак, мы хотим сделать бинарный патч между версией от 8е апреля и версией за 18е. Нужен ли нам весь 8гб дамп за 8е апреля? Не-а :) Достаточного его signature файла!

Итак, создаем инкрементальный бэкап не имея полного бэкапа на руках (вообще!):
time rdiff delta /root/56640.signature /vz/tmp/56640.hdd /vz/tmp/56640_diff_between_8_and_18_april.rdiff

И на выходе мы получим дельта-файл между бэкапами за 8е и 18е апреля :)


Но есть одно но, ОН ОЧЕНЬ МЕДЛЕННЫЙ:
real    13m27.094s
user    13m14.457s
sys    0m9.089s
Но при этом бесконечно радует размер файла инкремента:
ls -alh /vz/tmp/56640_diff_between_8_and_18_april.rdiff
-rw-r--r-- 1 root root 447M Апр 18 00:37 /vz/tmp/56640_diff_between_8_and_18_april.rdiff

Теперь попробуем обратный процесс создание полного бэкапа за 18е апреля из дельты + бэкапа за 8е.

Эти тесты я не уверен, что проведу сегодня, так что пока сделаем лишь чексуммы:
sha1sum /vz/tmp/56640.hdd
1580e28b7c23f390e02c30d62f10971a77b9ace8  /vz/tmp/56640.hdd
Также об ускорении. Решил попробовать увеличить блок обработки до 1 мегабайта. Для этого нужно регенерировать signatures файл:

rdiff --statistics  --block-size=1048576 signature 56640_root_hdd.gz_84cab040-bed0-11e3-b5aa-80259087d80c /root/56640.signature
Запускаем создание дельты снова:

 time rdiff --statistics  --block-size=1048576 delta /root/56640.signature /vz/tmp/56640.hdd /vz/tmp/56640_diff_between_8_and_18_april.rdiff
Он сразу сообщит, что используется на порядок меньше блоков (стандартный блок - 2048 байт):

rdiff: loadsig statistics: signature[7938 blocks, 1048576 bytes per block]
Ура! Победа :)
real    2m30.670s
user    2m17.618s
sys    0m10.665s
Но не во всем, сам дельта файл оказался крайне огромный:
ls -alh  /vz/tmp/56640_diff_between_8_and_18_april.rdiff
-rw-r--r-- 1 root root 3,9G Апр 18 01:26 /vz/tmp/56640_diff_between_8_and_18_april.rdiff
Так что с оптимизацией тут нужно быть поосторожнее :(


Wednesday, 16 April 2014

Как импортировать исходный код OpenVZ в GIT для удобной навигациии по коду и контроля за изменениями в коде?

Я уже положил код актуального ядра в Git для удобства: https://github.com/pavel-odintsov/openvz_rhel6_kernel_mirror

Вот так:
cd /usr/src
wget http://download.openvz.org/kernel/branches/rhel6-2.6.32/042stab108.1/vzkernel-2.6.32-042stab108.1.src.rpm
rpm -ihv vzkernel-2.6.32-042stab108.1.src.rpm
yum install -y rpm-build redhat-rpm-config unifdef # необходимы для патчей
yum install -y patchutils xmlto asciidoc elfutils-libelf-devel zlib-devel  elfutils-devel newt-devel python-devel bison flex hmaccalc binutils-devel audit-libs-devel
cd /root/rpmbuild/SPECS/
После этого нужно внести правки:
vim kernel.spec
выпиливаем там: перл модуль на который ругается rpmbuild: ExtUtils::Embed
 Накладываем патчи:
rpmbuild -bp  kernel.spec

cd /root/rpmbuild/BUILD/kernel-2.6.32-504.16.2.el6/linux-2.6.32-042stab108.1
git init
git add --all

git commit -m "Initial Commit"
git remote add origin ssh:/путь к вашему репо.git
git push origin master
А если делается обновление, то обновить файлы в репо можно так:
/bin/cp -R * /usr/src/openvz_rhel6_kernel_mirror/

P.S. OpenVZ team, я знаю, что Вы меня временами читаете, пожалуйста, сделайте хотя бы по релизным версиям git репо =)

Wednesday, 2 April 2014

Огромная разница в скорости выполнения sha1sum и openssl sha1, откуда и почему?

В процессе отладки нашего бэкап решения обратил внимание, что хэш функции стали потреблять много процессорного времени и совершенно случайно обнаружил следующее:
[root@technode4 ~]# time sha1sum /vz/private/7803/root.hdd/root.hdd
c41be08852baed71294623ea27ec7f64a3ac117f  /vz/private/7803/root.hdd/root.hdd

real    1m1.632s
user    0m59.987s
sys    0m1.663s


[root@technode4 ~]# time openssl sha1 /vz/private/7803/root.hdd/root.hdd
SHA1(/vz/private/7803/root.hdd/root.hdd)= c41be08852baed71294623ea27ec7f64a3ac117f

real    0m17.130s
user    0m16.035s
sys    0m1.093s
То есть, типовая/привычная/понятная sha1sum, используемся везде и вся откровенный тормоз. Почему?

Да, тесты проведены корректно, до запуска хэширования страничный кэш Linux был прогрет и все тесты были проведены по 3-5 раз со сходными результатами. 

Saturday, 22 March 2014

Подскажите аналог parted -lsm?

Вот с такой выдачей:
parted -lsm
BYT;
/dev/sda:599GB:scsi:512:512:msdos:Adaptec Device 0;
1:1049kB:17,2GB:17,2GB:linux-swap(v1)::;
2:17,2GB:599GB:582GB:ext4::;
Нужен листинг всех дисковых устройств.

Thursday, 20 March 2014

Установка Jira на Debian 7 Wheezy

Ставим Java: http://www.stableit.ru/2014/03/java-7-debian-7-wheezy.html

Стягиваем дистрибутив:
tar -xf atlassian-jira-6.2.1-bundle.tar.gz  -C /opt/

После этого вот отсюда - http://dev.mysql.com/downloads/connector/j/ -  стаскиваем platform Independent Java MySQL Connector.


tar -xf mysql-connector-java-5.1.29.tar.gz
cp mysql-connector-java-5.1.29/mysql-connector-java-5.1.29-bin.jar /opt/atlassian-jira-6.2.1-standalone/lib

Создаем юзера:
/usr/sbin/useradd --create-home --comment "Account for running JIRA" --shell /bin/bash jira
Указываем пути до папок данных:
vim /opt/atlassian-jira-6.2.1-standalone/bin/setenv.sh

Там корректируем:
JIRA_HOME="/opt/jira_data"
Запускаем инсталлер:

/opt/atlassian-jira-6.2.1-standalone/bin/start-jira.sh
Потом открываем: http://x.x.x.x:8080/ и начинаем установку, выбираем внешнюю БД.

Создаем БД.

После этого создаем в MySQL юзера для stash: http://www.stableit.ru/2009/12/mysql-debian5-lenny.html


Саму базу создаем вот так:
mysql -uroot -p
SET GLOBAL storage_engine = 'InnoDB';
CREATE DATABASE jira CHARACTER SET utf8 COLLATE utf8_bin;
GRANT ALL PRIVILEGES ON stash.* TO 'jira'@'localhost' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
QUIT;
Все, далее конфигурируем мастер :)

А для автозапуска добавляем в /etc/rc.local команду:
/opt/atlassian-jira-6.2.1-standalone/bin/start-jira.sh

Наименее геморройный способ поставить Java 7 на Debian 7 Wheezy

Архивчик нужно стянуть с офсайта java.com.

Ставим Java 1.7:

tar -xf jre-7u51-linux-x64.gz  -C /opt
MYJAVAHOME=/opt/jre1.7.0_51
Добавляем свеже установленную java в систему:
update-alternatives --install /usr/bin/java java ${MYJAVAHOME%*/}/bin/java 20000
Убеждаемся, что все ок:
java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)

Установка Atlassian Stash на Debian 7 Wheezy

Я опускаю тот факт, что до начала установки у Вас должна быть лицензия и дистрибутив Stash.

Ставим основные зависимости:
apt-get install -y perl git  

Ставим Java 1.7: http://www.stableit.ru/2014/03/java-7-debian-7-wheezy.html

Ставим MySQL  сервер:
apt-get install -y mysql-server

После этого создаем в MySQL юзера для stash: http://www.stableit.ru/2009/12/mysql-debian5-lenny.html

Но базу нужно создавать особенным образом:
mysql -uroot -p
SET GLOBAL storage_engine = 'InnoDB';
CREATE DATABASE stash CHARACTER SET utf8 COLLATE utf8_bin;
GRANT ALL PRIVILEGES ON stash.* TO 'stashuser'@'localhost' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
QUIT;
После этого вот отсюда - http://dev.mysql.com/downloads/connector/j/ -  стаскиваем platform Independent Java MySQL Connector.
tar -xf mysql-connector-java-5.1.29.tar.gz  tar -xf atlassian-stash-2.11.4.tar.gz
cd atlassian-stash-*
cp ваш_путь/mysql-connector-java-5.1.29/mysql-connector-java-5.1.29-bin.jar  lib/
После этого переносим папку устанощика в /opt, так как это будет рабочая папка stash:
mv atlassian-stash-2.11.4 /opt/
cd /opt/atlassian-stash-2.11.4
STASH_HOME=/opt/stash ./bin/start-stash.sh


После этого открываем:
http://78.47.9.180:7990

Там выбираем external database.  После этого завершаем мастер установки.

Теперь нужно настроить автозапуск после ребута:

vim ./bin/setenv.sh

и на строке: 
STASH_HOME="/opt/stash"
Запуск должен осуществляться вот таким скриптом:
/opt/atlassian-stash-2.11.4/bin/start-stash.sh 
Его можно добавить в самый низ /etc/rc.local и для теста ребутнуть машину.


Monday, 17 March 2014

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

Суть вопроса - как сравнить версию динамической либы, которая загружена в память программы с той, которая имеется на диске? Если подразумевается, что в пути к либе версия не указана.

Итак, обычно версия либы закодирована в пути, то есть для Bind:

cat /proc/29743/maps |grep xml
7f074fdfc000-7f074ff43000 r-xp 00000000 08:03 7782687                    /usr/lib/libxml2.so.2.7.8
7f074ff43000-7f0750142000 ---p 00147000 08:03 7782687                    /usr/lib/libxml2.so.2.7.8
7f0750142000-7f075014b000 rw-p 00146000 08:03 7782687                    /usr/lib/libxml2.so.2.7.8



Тут все очевидно, загружена нужная нам версия.

Но как быть, если версия не указана в пути?

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

cat /proc/29743/maps |grep xml|grep 'r-xp'
7f074fdfc000-7f074ff43000 r-xp 00000000 08:03 7782687                    /usr/lib/libxml2.so.2.7.8

Тут 7f074fdfc000-7f074ff43000 - соотвественно, адреса начала и конца областей памяти в которые ммапнута либа в конкретном процессе (от процесса к процессу они различные).

7782687 - это айнод на диске.

Айнод - первый способ проверить, перегрузилась либа при апгрейде или нет. Если айнод совпадает с тем, что на диске, то все ок:


ls -li  /usr/lib/libxml2.so.2.7.8
7782687 -rw-r--r-- 1 root root 1374168 Oct 13 09:43 /usr/lib/libxml2.so.2.7.8

Как мы видим - совпало!

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

Тут нам поможет gdb, им можно снять нужные нам области памяти.


gdb --batch --pid 29743 --ex  "dump memory /root/memory_new.dat 0x7f074fdfc000 0x7f074ff43000"

Как видите, мы указали пид процесса и диапазоны памяти ммапинга снабженные префиксом 0x (указываем на 16 ричный формат).
В итоге мы поулчаем файл примерно равный по объему изначальному файлу на диске:

ls -al /root/memory.dat
-rwxr-xr-x 1 root root 1339392 Jan  3 15:58 /root/memory.dat

root@stat:~# ls -la /usr/lib/libxml2.so.2.7.8
-rw-r--r-- 1 root root 1374168 Oct 13 09:43 /usr/lib/libxml2.so.2.7.8

Почему объем иной - я сказать не могу, скоее всего ммапинг наичнается с определенного адреса памяти.

Но это полноценный эльф файл:

file /root/memory.dat
/root/memory.dat: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, stripped

Правда, при запуске он сегфолтится.

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


strings  /root/memory.dat |egrep '^[0-9\.\-]+$'
1.2.3.4
20708
00000
01050


Как можно догадаться, версия тут 20708, это закодированный формат 2/7/8.

Теперь проверить, какая версия у либы на диске:

strings /usr/lib/libxml2.so.2.7.8 |egrep '^[0-9\.\-]+$'
1.2.3.4
20708
00000
01050



Как мы видим - совпадение полное!!! ура!!!!!

Для понимания разницы приведу пример выдачи команды при версии 2/8/0:

strings /usr/lib/x86_64-linux-gnu/libxml2.so.2.8.0 |egrep '^[0-9\.\-]+$'
1.2.7
20800
00000
01050



Можно углубить анализ далее.


xxd /usr/lib/libxml2.so.2.7.8 lib.hex
xxd /root/memory_new.dat mem.hex

Теперь првоерим, в чем их отличия:

diff -u  mem.hex lib.hex |wc -l
2180

Как видим 2180 строк отличий.

Но!!! Это не отличия, это лишь сигнализация о том, что mem.hex усечен относительно самой либы (не знаю по каким причинам):

Убедимся в этом:

diff -u  mem.hex lib.hex |egrep '^+' |wc -l
2180

Вот так мы подтверждаем факт идентичныости 99% данных либ.


Есть еще вариант: проверить наличие либы в страничном кэше после его обнуления.


wget https://raw.github.com/hoytech/vmtouch/master/vmtouch.c
gcc -Wall -O3 -o vmtouch vmtouch.c



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

echo 3 > /proc/sys/vm/drop_caches

./vmtouch /usr/lib/libxml2.so.2.7.8
          Files: 1
    Directories: 0
 Resident Pages: 336/336  1M/1M  100%
        Elapsed: 7.4e-05 seconds



Пару слов о том, каким должен быть системный администратор :)

Всем привет :)

Предлагаю к прочтению статью http://samag.ru/archive/article/2648, где есть небольшая заметка от нас какими мы видим для себя ТРУ системных администраторов.

Sunday, 16 March 2014

Установка и использование Intel dpdk 1.7.1 на Debian Wheezy

Что это и зачем: http://dpdk.org или http://www.intel.ru/content/dam/www/public/us/en/documents/presentation/dpdk-packet-processing-ia-overview-presentation.pdf Впрочем, если Вы нашли мою запись, то, очевидно, знаете, для чего оно Вам и что это =)


Оговоримся, что тесты идут с картой Intel 540 :
01:00.0 Ethernet controller: Intel Corporation 82599EB 10-Gigabit SFI/SFP+ Network Connection (rev 01)

Ставим зависимости:

apt-get install gcc-multilib
Компилируем:
cd /usr/src
wget http://dpdk.org/browse/dpdk/snapshot/dpdk-1.7.1.tar.gz
tar -xf dpdk-1.7.1.tar.gz
cd dpdk-1.7.1
make install T=x86_64-native-linuxapp-gcc
make install  T=x86_64-default-linuxapp-gcc
Грузим модули (Модуль Userspace I/O, он стандартный в Linux):
modprobe uio
Загружаем драйвер dpdk:
insmod ./x86_64-native-linuxapp-gcc/kmod/igb_uio.ko
Биндим все интерфейсы на сетевых интел для работы с igb_uio.

Получаем адреса всех наших сетевых, которые планируется использовать для теста:
tools/dpdk_nic_bind.py --status

Network devices using DPDK-compatible driver
============================================
<none>

Network devices using kernel driver
===================================
0000:02:00.0 'I350 Gigabit Network Connection' if=eth0 drv=igb unused=igb_uio *Active*

Other network devices
=====================
0000:02:00.1 'I350 Gigabit Network Connection' unused=igb_uio
0000:02:00.2 'I350 Gigabit Network Connection' unused=igb_uio
0000:02:00.3 'I350 Gigabit Network Connection' unused=igb_uio
0000:0a:00.0 '82599EB 10-Gigabit SFI/SFP+ Network Connection' unused=igb_uio
0000:0a:00.1 '82599EB 10-Gigabit SFI/SFP+ Network Connection' unused=igb_uio
0000:0d:00.0 '82599EB 10-Gigabit SFI/SFP+ Network Connection' unused=igb_uio
0000:0d:00.1 '82599EB 10-Gigabit SFI/SFP+ Network Connection' unused=igb_uio
 И теперь для каждой сетевой, которую будем использовать с DPDK делаем вот так:
tools/dpdk_nic_bind.py --bind=igb_uio 0000:0d:00.1
После этого, убеждаемся, что все сетевые нужные нам появились в блоке "Network devices using DPDK-compatible driver":
tools/dpdk_nic_bind.py --status

Network devices using DPDK-compatible driver
============================================
0000:0a:00.0 '82599EB 10-Gigabit SFI/SFP+ Network Connection' drv=igb_uio unused=
0000:0a:00.1 '82599EB 10-Gigabit SFI/SFP+ Network Connection' drv=igb_uio unused=
0000:0d:00.0 '82599EB 10-Gigabit SFI/SFP+ Network Connection' drv=igb_uio unused=
0000:0d:00.1 '82599EB 10-Gigabit SFI/SFP+ Network Connection' drv=igb_uio unused=

Network devices using kernel driver
===================================
0000:02:00.0 'I350 Gigabit Network Connection' if=eth0 drv=igb unused=igb_uio *Active*

Other network devices
=====================
0000:02:00.1 'I350 Gigabit Network Connection' unused=igb_uio
0000:02:00.2 'I350 Gigabit Network Connection' unused=igb_uio
0000:02:00.3 'I350 Gigabit Network Connection' unused=igb_uio
После этого трафик прекратит захватываться по всем этим интерфейса и передаваться в сетевой стек Linux.


Теперь резервируем блок huge tlb pages, необходимых для работы приложения:
mkdir -p /mnt/huge
mount -t hugetlbfs nodev /mnt/huge
echo 64 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages
Выставляем высшую частоту процессора:
for gov in /sys/devices/system/cpu/*/cpufreq/scaling_governor ; do echo performance >$gov ; done
Собираем примеры:
cd examples
export RTE_TARGET=x86_64-native-linuxapp-gcc
export RTE_SDK=/usr/src/dpdk-1.7.1
make
Запускаем:
build/helloworld -n 2 -c 7
Как тестер еще можно использовать:
build/app/testpmd -c7 -n3 -- -i --nb-cores=2 --nb-ports=1
Вот пример дефрагментатора пакетов:
./ip_fragmentation -c 1 -n 1 -- -p 1
Источник: http://blog.csdn.net/linzhaolover/article/details/9452641



Thursday, 13 March 2014

Как для libvirt указать собственные пути до сертификатов для подключения?

Вот так, через ключ pkipath:
virsh -c qemu+tls://srv1.domain.ru/system?pkipath=/etc/srv1 list
А в папке /etc/srv1 должны лежать следующие сертификаты:
cacert.pem
clientcert.pem
clientkey.pem
Источник: https://www.redhat.com/archives/libvirt-users/2011-March/msg00034.html

Spice Viewer/Client for Mac OS

Качаем тут: http://people.freedesktop.org/~teuf/spice-gtk-osx/dmg/0.5.7/

Вроде бы другого не существует вообще.

Сборка PHP libvirt на Debian 7 Wheezy из git

Собираем:
apt-get install -y libvirt-dev php5-dev libxml2-dev xsltproc libxml2-utils
cd /usr/src
git clone git://libvirt.org/libvirt-php.git
cd libvirt-php
autoreconf
./configure
make

При сбокре из git мы получим ошибку:
libvirt-php.c: In function ‘zm_startup_libvirt’: libvirt-php.c:1179:2: error: ‘VIR_DOMAIN_VCPU_GUEST’ undeclared (first use in this function) libvirt-php.c:1179:2: note: each undeclared identifier is reported only once for each function it appears in

Так как в wheezy старый либвирт, а именно в файле:
vim /usr/include/libvirt/libvirt.h 

Прямо под строкой:
VIR_DOMAIN_VCPU_MAXIMUM = (1 << 2), /* Max rather than current count */

Нужно добавить:
VIR_DOMAIN_VCPU_GUEST   = (1 << 3), /* Modify state of the cpu in the guest */  

Выкатываем его:
cp src/libvirt-php.so /usr/lib//php5/20100525/
Добавляем в конфиг:
echo "extension=libvirt-php.so" > /etc/php5/conf.d/libvirt-php.ini
Вуаля:
php -m | grep libvirt libvirt