Highlighter

четверг, 31 мая 2012 г.

Пробуем на вкус systemd

Я тут немножко приболел и в свободное время захотелось пощупать systemd в gentoo, и потавил его на компьюетер, который используется у меня как мультимедиа-центр.
Особенностью этого компьюетера явялется то, что домашняя папка пользователя shtsh (из-под которого запущен xbmc) и /usr/portage монтируются по сети, используя nfs.

Пара слов о systemd. Этот проект разрабатывается как современная, гибкая и быстрая замена существующих систем инициализации и породила множество споров (бинарные логи! зачем нужен ещё один велосипед?!). Однако в него уже влился проект udev и к нему намертво привязали Gnome. Кроме того, systemd продвигается RedHat и уже входит в состав Fedora, что заставляет подозревать, что в RHEL 7 (в крайнем случае 8) и его форках (CentOS, Scientific Linux, Oracle Linux и проч.) systemd будет. А в Mageia, Mandriva, OpenSUSE уже есть. В debian, gentoo, archlinux доступен для отдельной установки.

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

Сначала, я чтобы не заморачиваться, прописал в USE-флаги systemd. Затем обновил систему при помощи emerge -avuDN @world. Потом приступил к настройкам по мануалу.
После настройки ядра, установки и прописывания в grub, мне понадобилось следующее.

Включить сеть, которая у меня настраивается при помощи DHCP.
systemctl enable dhcpcd.service
Включить ssh
systemctl enable sshd.service
После этого я посмотрел статус загрузки (вывод systemctl) и понял, что NFS шары не монтируются, так как на момент монтирования ещё недоступна сеть. Поэтому пришлось разбираться. Для этого я сделал следующее:

Создал в /etc/systemd/system файлы с настройками монтирования
mnt-disk.mount
[Unit]
Description=/mnt/disk NFS share
Wants=rpc-statd.service
After=network.target

[Mount]
What=server.home:/mnt/disk
Where=/mnt/disk
Type=nfs
usr-portage.mount
[Unit]
Description=/usr/portage NFS share
Wants=rpc-statd.service
After=network.target

[Mount]
What=server.home:/usr/portage
Where=/usr/portage
Type=nfs 

Затем заставил их подключаться при загрузке:
ln -s /etc/systemd/system/mnt-disk.mount /etc/systemd/system/multi-user.target.wants/mnt-disk.mount
ln -s /etc/systemd/system/usr-portage.mount /etc/systemd/system/multi-user.target.wants/usr-portage.mount

В отличии от мануала,  у меня не было xdm.service, поэтому пришлось думать, как сделать свой.
/etc/systemd/system/slim.service
[Unit]
Description=SLIM Display Manager
Wants=dbus.target
Before=bluetooth.target getty.target vixie-cron.service
After=network.target acpid.service mnt-disk.mount

[Service]
ExecStart=/usr/bin/slim -nodaemon
Restart=always

[Install]
Alias=display-manager.service
WantedBy=graphical.target

И включить его запуск
systemctl enable slim.service

В результате у меня запускался slim и xbmc только после того, как смонтируется домашняя папка, расположенная на сетевой шаре /mnt/disk.

Стоит отметить, что по своим настройкам systemd сильно отличается от остальных систем загрузки. В частности, эти самые service, target, mount. Однако всё это достаточно подробно (по крайней мере, лучше, чем я могу рассказать) расписано в манах. В частности в systemd.service, systemd.target, systemd.mount и прочие. Аналогично с пунктами настроек. Онлайн можно посмотреть по этой ссылке.

Также стоит обратить внимание, что системный лог ведётся в своём формате и его можно смотреть утилитой systemd-journalctl. Я так понял, что можно использовать /dev/kmesg, но пока не разобрался, как.

Выводы:
  • Диалог приветствия при использовании systemd появляется буквально через несколько секунд после загрузки (без использования SSD!), однако сеть и прочее подключаются после этого.
  • Как следствие из вышесказанного - есть смысл отказаться от хомяка через NFS, что сильно ускорит загрузку xbmc. Собственно, я так и сделал.
  • Systemd очень сильно отличается от других систем инициализации и с её настройкой действительно нужно отдельно разбираться. Хотя, может, когда она начнёт массово использоваться, появится много подробных howto.
  • Пока непонятно, зачем это нужно - 5-10 секунд выигрыша при загрузке, когда сейчас основной тормоз- скорость инициализации оборудования до загрузки ОС, особенно на серверах. Но серверы и загружаются крайне редко.
  • Пока что единственную пользу вижу в одном - возможность рестарта демона при падении. Но это не так и часто нужно.

вторник, 15 мая 2012 г.

Дамб БД mysql по ssh

Проблема: есть сервер БД, где мало свободного места (на дамп не хватит). Нужно сделать дамп БД.

Решение:
ssh -T <user>@<host> “mysqldump -u <db_user> -p <other switches> database | bzip2 -9” | bzip2 -dc > database.dump

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

вторник, 1 мая 2012 г.

Делаем из AMI vmdk

Есть амазоновский образ диска ami, нужно запустить его в виртуалке. Используется virtualbox. Попутно создадим образ диска другого формата (любой, поддерживаемый VB)

Это делается, в принципе, несложно.
Сначала нужно скачать Amazon EC2 AMI Tools.
Дальше поставить ruby и расшифровать образ.
Утилиты от амазона лежат в /media/sf_Common/ec2-ami-tools, образ лежит в папке /media/sf_Common/jira.

Для того, чтобы утилиты работали, нужно указать папку, где они находятся.
 export EC2_HOME=/media/sf_Common/ec2-ami-tools
Дальше распаковываем
/media/sf_Common/ec2-ami-tools/bin/ec2-unbundle -k our_private_key.pem -d /media/sf_Common -s /media/sf_Common/jira -m /media/sf_Common/jira/image.manifest.xml

После этого у нас появился файл image в папке /media/sf_Common/, это образ раздела.
Теперь у нас есть два варианта: создать виртуальный диск, с такими же характеристиками, как и у образа, либо просто примонтировать и скопировать всё с сохранением прав. Я выбрал второй вариант.

Создаём раздел на sdb и на sdb1 создаём файловую систему ext3.
Затем монтируем образ в /tmp/a, а наш диск в /tmp/b
mount -o loop /media/sf_Common/image /tmp/a
mount /dev/sdb1 /tmp/b

Копируем всё с сохранением прав
cp -ra /tmp/a/* /tmp/b

После этого чрутимся в новую систему
mount -t proc proc /tmp/b/proc
mount -o rbind /dev /tmp/b/dev
chroot /tmp/b/

ставим grub
grub
root (hd1,0)
setup (hd1)
quit

Проверяем, что у нас прописан правильный раздел в /boot/grub/menu.lst, выключаемся, удаляем все диски, которые не нужны и пробуем загрузиться. Мне пришлось дополнительно отредактировать /etc/inittab и раскомментировать строчку
1:2345:respawn:/sbin/mingetty tty1

В результате система стала предлагать залогиниться локально.
Ещё проблема может быть с тем, что в virtualbox нереально загрузиться с xen, но тут было обычное ядро.

четверг, 19 апреля 2012 г.

Готовим NFS в домашних условиях

Получилось так, что у меня есть ноутбук с довольно современным железом и приличным винтом, и которым я совершенно не пользуюсь.
Чтобы ноут не простаивал, было принято волевое решение поставить туда генту без иксов и без всякого мусора и получить бесшумную и энергоэффективную торрентокачалку. В будущем поставлю туда nagios, настрою музыку при проблемах и смогу немножко поспать во время ночных дежурств :)

К сожалению, мой роутер не умеет DNS, поэтому имена серверов пришлось проприсывать в /etc/hosts. Соответственно, у меня сейчас два домашних сервера: torrents и media. Так как на обоих серверах стоит Gentoo, то я решил сделать им общий /usr/portage, чтобы по десять раз не качать одно и то же. Ну, и какой-нибудь /media/disk на 650 ГБайт, чтобы доступ был откуда нужно.

Как оказалось, настройка NFS элементарна:
  • Нужно проверить, что в ядре включена поддержка
  • Нужно на сервере указать, кто может получать доступ и к чему
  • Нужно на клиенте примонтировать разделы
Это не считая того, что можно вообще корень держать на сетевой шаре. Или иметь общий /usr на NFS. Правда в таком случае придётся делать initramfs, ибо сейчас идёт интеграция с новым udev и systemd.

Итак, укажем на сервере, что экспортировать. Для этого есть файл /etc/exports

# /etc/exports: NFS file systems being exported.  See exports(5).
/usr/portage 192.168.2.254(async,rw,no_subtree_check)
/media/disk 192.168.2.1/24(ro,no_subtree_check)
/media/disk 192.168.2.254(rw,no_subtree_check)

Получается что к /usr/portage и /media/disk будет иметь полный доступ 192.168.2.254. А 192.168.2.1-192.168.2.254 будут спобны только читать /media/disk. Также можно использовать имя сервера вместо IP. То есть у меня прописано так:

/usr/portage media(async,rw,no_subtree_check)

И сервер media сможет получить доступ к шаре (в данном случае имя прописано в /etc/hosts).
Список опций, что указаны в скобках можно получить тут.

Теперь осталось прописать монтирование. Делается это банально - в fstab добавляется строчка вроде следующей:

torrents:/usr/portage           /usr/portage    nfs             defaults        0       0

после этого добавляем nfsmount в автозапуск на клиенте, nfs на сервере и радуемся.

Но и это ещё не всё. В Windows, начиная с 7 появилась возможность монтирования NFS-шар. Для этого нужно доустановить Services for NFS и можно монтировать раздел.

mount \\torrents\media\disk z:

И иметь доступ к файлам.
 

вторник, 10 апреля 2012 г.

Собираем RPM пакет в CentOS

Ставить из исходников в бинарном дистрибутиве при помощи make install как-то неправильно. Это очень успешно засоряет систему и мешает обновлениям. Поэтому будем разбираться, как собрать пакет в CentOS.

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

yum install -y rpmdevtools

Ну и естественно, то что требуется для сборки конкретного пакета (make, gcc и прочее).
Теперь создадим пользователя, чтобы не делать потенциально опасные операции под рутом и залогинимся под ним.

useradd rpmbuild
su - rpmbuild
cd

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

rpmdev-setuptree

Идём в папку SOURCE и качаем туда приложение, которое будем собирать. В моём случае это pgpool-II. Выдернем из архива pgpool.spec - это файл, где и описана сборка rpm-пакета. Вот его и будем использовать. Посмотрев в него, видно, что он слегка неактуален, поэтому будем исправлять, структура простая.

Сначала идёт заголовок, поля которого говорят сами за себя, тут нам достаточно прописать нужную версию (у нас 3.1). Ещё хочется обратить внимание на то, что можно указывать на несколько исходных файлов и патчей и на то, как это делается. Так как они описаны в этих полях, то их тоже нужно достать из архива и положить в папку SOURCE.
Ссылки на пути даются в виде переменных, например, ссылка на скачивание выглядит так:
Source0:    http://pgfoundry.org/frs/download.php/2423/%{name}-%{version}.tar.gz
Соответственно, тут %{name} = pgpool-II, а %{version} = 3.1 и ссылка получается http://pgfoundry.org/frs/download.php/2423/pgpool-II-3.1.tar.gz

Далее идёт описание, сборка и установка. О том, какие разделы есть, можно почитать в интернете, например тут. Также стоит обратить внимание, что есть секции devel - в них описаны параметры сборки -devel пакета, как можно догадаться.

Теперь попытаемся собрать пакет

rpmbuild -bb pgpool.spec

Затем установим зависимости и опять попытаемся собрать. Затем закомментируем патч (который изменяет настройки по-умолчанию - всё равно будем под себя настраивать) и опять попытаемся собрать. Затем добавим новые появившиеся файлы в секцию %files и наконец-то всё соберётся. Как видите, ничего особо сложного - главное читать, на что ругнётся rpmbuild. В результате у нас получилось два пакета: pgpool-II-3.1-3.el6.x86_64.rpm  pgpool-II-devel-3.1-3.el6.x86_64.rpm, которые можно устанавливать и использовать.

Теперь давайте попробуем написать минимальный spec с нуля. Соберём пакет c uwsgi. Его сборка представляет собой просто выполнение команды make. К сожалению, ни spec, ни даже make install они не предоставляют. Поэтому будем делать всё руками. К счастью, vim при создании нового spec-файла подставил заготовку с пустыми полями.

Вот, что у меня вышло:

Name:        uwsgi
Version:    0.9.9.2
Release:    1%{?dist}
Summary:    uWSGI application server

License:    GPL
URL:        http://projects.unbit.it/uwsgi
Source0:    http://projects.unbit.it/downloads/%{name}-%{version}.tar.gz
BuildRoot:    %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)

# Всё, кроме chrpath взято из их гайда по сборке
BuildRequires:    libxml2-devel python-devel chrpath
Requires:    libxml2

%description
uWSGI is a fast, self-healing and developer/sysadmin-friendly application container server coded in pure C.

%prep
%setup -q

%build
make %{?_smp_mflags}

%install
# следующие две строчки - костыль, так как по умолчанию папки /usr/bin и /etc будут
install -d $RPM_BUILD_ROOT%{_bindir}
install -d $RPM_BUILD_ROOT%{_sysconfdir}

# Устанавливаем файлы uwsgi и uwsgi.xml в /usr/bin и /etc соответственно.
install %{name} $RPM_BUILD_ROOT%{_bindir}
install uwsgi.xml $RPM_BUILD_ROOT%{_sysconfdir}

# А вот это довольно важная команда. При линковке uwsgi были жёстко прописаны пути
# к библиотекам, что плохо, так как нужно пользоваться динамическим линкером.
# Поэтому это безобразие нужно убрать, для чего используется следующая команда.
# Подробней можно почитать тут.
chrpath --delete $RPM_BUILD_ROOT%{_bindir}/%{name}

%clean
rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
%doc
%{_bindir}/%{name}
%{_sysconfdir}/uwsgi.xml


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

среда, 4 апреля 2012 г.

Linux ate my RAM.

Господа.
К сожалению, многие толковые люди не умеют пользоваться командой free.

$ free -m
             total       used       free     shared    buffers     cached
Mem:          1504       1491         13          0         91        764
-/+ buffers/cache:        635        869
Swap:         2047          6       2041

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

И хорошая ссылка напоследок: http://www.linuxatemyram.com/

Как работает OOM Killer

Когда приложение пытается сделать memory allocation, а доступная память закончилась, в linux запускается процесс OOM Killer. Как можно понять из названия, он создан для того, чтобы УБИВАТЬ!11.

Но, естественно, убивает он не всё подряд, а подчиняясь определённым правилам:
  • Мы должны потерять минимум работы
  • Мы должны освободить много памяти
  • Мы не должны убивать невиновных в пожирании большого количества памяти
  • Мы хотим убить как можно меньше процессов (в идеале - один)
  • Результат работы должен быть предсказуемым
Далее идёт подсчёт очков виновности процессов и процессы (или потоки), набравшие больше всего баллов, жестоко убиваются.

Вот так идёт подсчёт очков:
  1. Считаем RSS процесса
  2. Добавляем RSS всех дочерних процессов
  3. Если процесс долго живёт, то значение уменьшается
  4. Если у процесса niceness больше 0, то значение увеличивается.
  5. Если есть флаги CAP_SYS_ADMIN или CAP_SYS_RAWIO, результат уменьшается
  6. Смотрится знаечение /proc/<pid>/oom_adj, которое может задавать пользователь, чтобы повышаться сопротивляемость OOM Killer'у. Вроде как это уже deprecated и нужно использовать oomscore_adj.
Естественно, это не точный алгоритм, цель написанного - дать представление, от чего зависит выбор кандидата на убийство