Про графики

September 17th, 2011 No comments

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

В таких случаях иногда может помочь графическое представление:
Read more…

Categories: Техноблог Tags:

Что делать с лишними клавишами на клавиатуре?

November 22nd, 2010 3 comments

На моей клавиатуре (Microsoft Natural) полно всяких кнопочек. Долгое время я их игнорировал, но недавно все-таки заставил их работать и дико доволен результатом.

microsoft natural

Для этого пришлось написать несколько скриптов, которые у меня живут в ~/quickscripts:

% ls -lh quickscripts
drwxr-xr-x   2 zed zed  39 2010-11-17 21:49 example
drwxr-xr-x   2 zed zed  39 2010-11-19 22:43 apache
lrwxrwxrwx   1 zed zed   6 2010-11-21 19:12 current -> apache
drwxr-xr-x   2 zed zed  28 2010-11-17 21:49 builder
-rwxr-xr-x   1 zed zed 269 2010-11-16 23:52 select-scripts
-rwxr-xr-x   1 zed zed 101 2010-11-19 19:53 show-current
% ls -lh current/
-rwxr-xr-x 1 zed zed 430 2010-11-19 22:43 cmdF
lrwxrwxrwx 1 zed zed   4 2010-11-17 20:55 cmd1 -> cmdF
lrwxrwxrwx 1 zed zed   4 2010-11-17 20:55 cmd2 -> cmdF

Вот какая за этим стоит идея: по дополнительным кнопкам вызываются скрипты ~/quickscripts/current/cmd{1,2,3}, где current – это симлинк на конкретный набор скриптов. Этих наборов несколько, каждый для какой-то отдельной задачи. Например, скрипты в директории apache вызывают /etc/init.d/apache2 reload|restart на разработческом сервере.

Чтобы выбрать конкретный набор скриптов я нажимаю на кнопку “5″:

Это окошко отображает скрипт select-scripts, он написан на kaptain + bash, вот как он выглядит:

#!/usr/bin/kaptain

start "Quickscript selector" -> dir @exec(script)="OK";

dir -> @list(`cd ~/quickscripts && ls | grep -vE 'select-scripts|current' `)=`cd ~/quickscripts && readlink current`;

script -> "cd ~/quickscripts && rm -f current && ln -s " dir " current";

Kaptain – удивительный по своей функциональности и лакончности фреймворк для создания несложных GUI, даже немного жаль, что нечасто возникает в этом необходимость.

Вот пример скрипта, по кнопке Favorites он выполняет какие-то рутинные действия на удаленном сервере, а по кнопке “1″ запрашивает аргумент через всплывающее окошко.

#!/bin/bash
id=`cat /tmp/task_id`
if [[ "`basename $0`" = 'cmdF' ]]; then
           cat > /tmp/r <<EOF
	     update BuildTasks set Log='', Status='waiting', Version='', Cancelled=0, RepositoryName='' where TaskID=$id
EOF
           a=`cat /tmp/r | ssh devserver 'killall builder </dev/null; mysql testdb' 2>&1 && echo "task $r was restarted"`
           rm /tmp/r
           notify-send -t 3000 'builder:' "$a"
else
           id=`zenity --entry --text="Task number" --entry-text="$id" || echo $id`
           echo $id > /tmp/task_id
fi

Результат работы отображается через libnotify:
kaptain dialog

В ubuntu для отображения уведомлений используется notify-osd, он всем хорош, но не поддерживает задание кастомных таймаутов (а по умолчанию – 10 секунд – это ужасно много), и не умеет отображать несколько уведомлений одновременно. Поэтому пришлось заменить его на старый вариант – notification-daemon, который поддерживает и то и другое:

apt-get remove notiy-osd
apt-get install notification-daemon

Осталось сказать, что запускать скрипты по нажатию на кнопку gnome умеет сам, и настраивается это в меню System->Preferences->Keyboard Shortcuts.

На этом все, буду рад, если кому-то мой опыт пригодится :)

Categories: Shell, Tips, Техноблог Tags:

Code Golf

May 26th, 2010 No comments

Мда.

Решили мы с другом поучаствовать в Code Golf на askdev.ru, с их задачкой по игре в города.
Закончили буквально за три минуты до завершения конкурса, и когда было пора отправлять решение, сайт лег :))

Решение вот такое:

#!/usr/bin/perl -CDAO
use utf8;
use List::Util qw/shuffle/;

my@a=qw{Калининград Вологда Далматово Дмитров Архангельск Владивосток Краков};

{@a=shuffle@a;(grep{$a[$_-1]=~/(.)(.)$/;$a[$_]!~/^$2/i&&$a[$_]!~/^$1/i|grep{/^$2/i}@a}1..$#a)&&redo}

print join ',', @a

По правилам этого конкурса подключение библиотек и вывод данных не учитывются, поэтому размер кода – 100 байт.

Восхитительные грабли.

April 28th, 2010 13 comments

Я недавно открыл для себя восхитительные грабли. Оказывается, что я ходил по ним годами, а наступил только вчера.

Допустим, нам нужно скачать какой-нибудь файлик из сети, посчитать его размер и сохранить в файл.

Код на perl будет примерно таким:

#!/usr/bin/perl -w
use strict;

if (system('wget -O- http://sveshnikov.ru/httpd.sh | wc -с > /tmp/size') != 0) {
        die "OMG! Can't count bytes in httpd.sh file!!!";
}

В дальнейшем этот скрипт используется примерно так: if ./get_value; then работаем с /tmp/size; else сообщаем куда нужно; fi

Так вот, у этого скрипта хромает надежность. Почему? И как это сделать правильно? Жду ваших вариантов, мой – завтра :)

UPD:

Проблема заключается в том, что при использовании пайпов в $? окажется результат последней выполненной команды:

$ blablabla | wc; echo $?
zsh: command not found: blablabla
      0       0       0
0

Я решил этот вопрос с помощью bash и его опции pipefail. Пример выше я бы переписал как-то так:

#!/usr/bin/perl -w
use strict;                                                                                                                                                                    

sub my_system {
      return system('bash', '-o', 'pipefail', '-c', @_);
}                                                                                                                                                                              

unless (my_system('wget -O- http://sveshnikov.ru/httpd.sh | wc > /tmp/size') == 0) {
      die "OMG! Can't count bytes in httpd.sh file!!!";
}

Теперь будут отлавливаться все ошибки.
В шелл-скриптах можно еще анализировать массив PIPESTATUS, в котором сохраняется exit code для всех команд ковейера, но мне показалось, что это неудобно.

Debian-пакеты с человеческим лицом на примере Zabbix 1.9

March 29th, 2010 2 comments

Кросс-пост с хабрахабра, в котором я описываю пример сборки debian-пакета с использованием CDBS.

UPD от 8 января 2012 года: статью переписал примерно наполовину. Сделал ее понятнее и актуальнее. Теперь в ней идет речь про Zabbix 1.9.8 и Ubuntu 11.10

Написать эту статью меня заставили две вещи. Во-первых, возникла необходимость поставить Zabbix на сервере, работающем под ubuntu. Заббикс – прекрасная система мониторинга, единственный значительный минус которой в моих глазах – это катастрофически неудобный интерфейс. Впрочем, от версии к версии он становится все менее ужасным, поэтому я всегда ставлю не стабильную версию, а beta или RC.

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

Связывает два этих события то, что zabbix 1.9 пока нет в репозиториях убунты, и в ближайшее время не появится, а делать configure && make && make install на продакшн-серверах, это, конечно, недостойное джентльмена занятие. В общем, появился хороший повод продемонстрировать, что debian-пакеты – это не страшно.

Итак, приступим:

1. Инициализация


apt-get install dh-make devscripts cdbs libmysqlclient-dev libcurl4-gnutls-dev
wget http://downloads.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Development/1.9.8/zabbix-1.9.8.tar.gz
tar zxvf zabbix-1.9.8.tar.gz
cd zabbix-1.9.8
dh_make -f ../zabbix-1.9.8.tar.gz --rulesformat cdbs --single

В результате будет создана дирекория zabbix-1.9.8/debian, с кучкой файлов внутри. Большинство из них нам не понадобится, и мы их удалим в конце, так что не пугайтесь :). Ключевую роль среди них играют 3-4 файла, ими мы и займемся.

Между делом, если бы мы пакетировали не zabbix, а более простую программу, которая обычно ставится с помощью ./configure; make; make install, то на этом создание пакета заканчивается. Осталось бы только собрать и установить пакет.

Но мы продолжим. Здесь и дальше я предполагаю, что вы находитесь в дирекории zabbix-1.9.8 (не в zabbix-1.9.8/debian).

2. Метаданные пакета.

Откроем файл debian/control и пропишем себя, любимого, в качестве создателя пакета, и укажем, какие пакеты должны приехать на сервер вместе с установкой zabbix. Для этого нужно найти строку ‘Depends’ (не путать с Build-Depends) и добавить в ее конец следующее: “fping, adduser, apache2, php5, php5-mysql, php5-gd”.

3. Выбор опций скрипта configure.

Обычно скрипт configure можно вызывать без параметров и он сгенерирует жизнеспособный конфиг, но для zabbix это не так – нужно отдельными опциями включать компиляцию серверной части и агента. Так как агент из репозитория ubuntu меня полностью устраивает, ограничимся сборкой только сервера. Для этого нужно дописать в конец файла debian/rules следующую строку:

DEB_CONFIGURE_USER_FLAGS := --enable-server --with-mysql --with-libcurl

4. Добавление файлов интерфейса в пакет.

Сборка пакета осуществляется следующим образом: создается временная директория (debian/имя_пакета), в которой в несколько этапов формируется его содержимое. Затем эта директория упаковывается в архив, добавляются метаданные, и все – пакет готов. Это очень грубое, но пока достаточное описание процесса. Бинарные файлы попадут в директорию debian/zabbix/usr/sbin сами собой (CDBS запустит команду make install DESTDIR=debian/zabbix), а про файлы php-интерфейса CDBS ничего не знает, поэтому нам придется указать на них самостоятельно. Для этого создадим файл debian/install вот с таким содержимым:

frontends/php/* usr/share/zabbix/
conf/zabbix_server.conf etc/zabbix

5. Создание пустых директорий.

Кроме того, для нормальной работы заббиксу нужны еще и директории для лог-файлов и локов. Они тоже являются частью пакета, поэтому создать их нужно прямо в той временной директории. Стандартный способ создания пустых директорий – перечисление их в файле debian/dirs:

/var/log/zabbix-server
/var/run/zabbix-server

6. Инит-скрипт.

В комплекте с заббиксом идет инит-сктипт (misc/init.d/debian/zabbix-server), но без обработки напильником он работать не будет. Поэтому лучше его заменить скриптом из убунты, который нужно сохранить под именем debian/init:


wget -O debian/init 'http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/oneiric/zabbix/oneiric/download/head:/zabbixservermysql.za-20090719032443-40a177i6799u0z76-876/zabbix-server-mysql.zabbix-server.init'

7. Logrotate.

Мы же труЪ-админы, а не халтурщики, поэтому создаем вот такой файл debian/logrotate:

/var/log/zabbix-server/zabbix_server.log {
daily
rotate 7
compress
missingok
notifempty
create 0640 zabbix zabbix
sharedscripts
}

О том, каким образом этот конфиг попадет в нужное место после установки пакета, думать не нужно :)

8*. Конфигурирование Apache, PHP и всего прочего

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

Итак, сконфигурируем веб-сервер:


mkdir misc/apache2-vhosts
cat > misc/apache2-vhosts/zabbix

ServerName zabbix
ServerAdmin admin@example.com
DocumentRoot /usr/share/zabbix
CustomLog /var/log/apache2/zabbix_access.log combined
ErrorLog /var/log/apache2/zabbix_error_log

^D
echo "misc/apache2-vhosts/zabbix etc/apache2/sites-available" >> debian/install

Затем займемся PHP:


mkdir misc/php.conf.d
cat > misc/php.conf.d/zabbix.ini
post_max_size = 16M
max_execution_time = 300
mbstring.func_overload = 2
max_input_time = 300
date.timezone = 'Europe/Moscow'
^D
echo "misc/php.conf.d/zabbix.ini etc/php5/apache2/conf.d" >> debian/install

И напоследок исправим в conf/zabbix_server.conf путь к лог-файлу (vim conf/zabbix_server.conf +39). Нужное нам значение: /var/log/zabbix-server/zabbix_server.log.

Можно подумать, что это было довольно бездумное решение – модифицировать исходный код пакета, поскольку это усложняет повторение процесса для следующей версии заббикса – нужно будет обязательно совершить эти правки еще раз.

К счастью, за нас об этом уже позаботились: после сборки пакета все внесенныые нами изменения (за пределами директории debian – т.е. в исходном коде софта), магическим образом появятся в директории debian/patches в виде патча. Поэтому все, что мы делаем с пакетом фактически сохраняется в директории debian.

9. Ручное вмешательство.

Иногда недостаточно просто разложить файлики по файловой системе, чтобы настроить среду для исполнения программы. В таких случаях на помощь приходят preinst, postinst, prerm и postrm скрипты, которые выполняются уже на сервере, куда пакет устанавливается. Названия у них вполне понятные, пояcнить нужно только то, что ‘inst’, и ‘rm’ – это фактическая распаковка или удаление содежимого пакета (все той же временной директории debian/zabbix, в нашем случае), кроме того – каждый из этих скриптов может вызываться с разными аргументами в зависимости от ситуации. Нам интересен скрипт postinst, вызывающийся с аргументом configure – нужное место скрипта можно легко найти в шаблоне postinst.ex. Приступим:


cd debian
mv postinst.ex postinst
vim postinst

Правим секцию configure:

...
configure)
# Создадим пользователя
useradd zabbix || echo "User zabbix was not added"

# Установим права на рабочие директории
chown zabbix:zabbix /var/log/zabbix-server /var/run/zabbix-server

# В этой директории веб-интерфейс пытается сохранить конфиг-файл, предоставим ему на это права:
chown www-data /usr/share/zabbix/conf
chmod 775 /usr/share/zabbix/conf

# Настроим автозапуск сервера:
update-rc.d zabbix defaults

# Включим новый virtualhost и перезапустим апач:
a2ensite zabbix
invoke-rc.d apache2 reload
;;

abort-upgrade|abort-remove|abort-deconfigure)

11*. Удаление ненужных шаблонов

В директории debian полно шаблонных конфигов и скриптов, которые нам на этот раз не пригодились:

rm debian/*.{ex,EX} debian/README.*

12. Сборка и установка.

Финишная прямая: запускаем сборку пакета командой debuild и, пропустив ругань на отсутствие электронной подписи мимо ушей, устанавливаем его командами:
dpkg -i ../package_name.deb
apt-get install -f

Это не очень красивый способ устанавливать пакет, но зато самый простой. Первая команда завершится с ошибкой, потому что dpkg не умеет самостоятельно устанавливать зависимости пакета. В результате пакет в системе останется, но будет в состоянии ‘broken’. Вторая команда все эти ошибки исправит. В случае, если все зависимости на месте, dpkg -i отработает без ошибок, и нужды во второй команде нет.

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

13*. Вышла новая версия Zabbix!

Распаковываем исходники, копируем директорию debian, выполняем инструкцию заново, начиная с 12-го шага.

Про винчестер на 2Гб и крутую ВЛБ-шную видюху :)

May 23rd, 2009 No comments

Гигабайты, мегагерцы.. сейчас они доступны всем и этим потеряли половину своей привлекательности.

То ли дело раньше: рассылаешь сообщение по левонетовским эхам, кто-то их читает, затем тебя будят звонком на ББС среди ночи и вызовом на чат (противная такая трель спикера). И вот как вы договариваетесь:

vasya> у меня есть Quantum Fireball 2.1Gb pазменяю на:(пеpечисляй)
me> – мультикаpта ISA
me> – 8mb simm 2x4mb
me> – HDD 270 + soft
me> – видеокаpта 2мб VLB
me> – 500 pуб
vasya> И ЭТО ВСЁ???
me> а что тебе еще надо
vasya> Ж:)
vasya> ОК
vasya> Пpоцесс сделки [..........]
vasya> Complete!
vasya> Завтpа тебе днем звякну… Ж:)
me> И еще. Раз ты говоpишь, что он пpоблемный, то давай манибяку в неделю
vasya> Чтол есть за манибяка такая?
me> деньги назад, если он не заpаботает
me> Ты говоpил, что не pаботал на целеpоне.
vasya> Мммм… Понимаешь – он ноpмально абсолютно pаботает без лагов, багов и глюков
vasya> Но на отдельном писи он почему-то тpебует вынуть из флоппика систем дискету…. очень сpанно… но ес
me> ВЫНУТЬ???
vasya> Да-да
vasya> Invalid System Disc
vasya> Please … disk and press any key…
me> аааа.. .
me> ну вобщем надо у меня пpовеpять.
me> лишь бы данные хpанил, и не теpял.
vasya> Все он хpанит – я с него мp3 дpужку таскаю иногда…
vasya> Вообщем если ты к своему 1.2 его поставишь – будет на уpа!
me> ну значит, все ок.
me> угу, тащи их тоже заодно.
vasya> Ну а видюха у тя (ВЛБ-шная) что такая кpутая?
me> ага, влб.
me> да, вполне
vasya> СИММ 8Мб – две платки по 8 микpосхем на каждой?
me> Я не помню, сколько там микpосхем, но по 4 мб каждая
vasya> Кста. музыку не забудь послушать… Ж:)
vasya> Лигалайз&D.O.B. – Настоящий Hip-Hop

p.s. кстати, у меня есть крутой комплект pentium overdrive, может нужен кому? Перечисляйте :)

Categories: общее, Техноблог Tags:

Магия в zsh

November 4th, 2008 3 comments

Захотелось мне в этот чудесный выходной понедельник поагитировать за свой любимый шелл. Чем, кстати, вообще может похвастаться какой-либо шелл, имея в конкурентах такого монстра, как bash? Ведь в bash есть все, что может только пожелать обычный пользователь. А, собственно, и нечем. Поэтому разработчикам zsh пришлось пойти на хитрость и добавить в свое детище некоторое количество магии :)

Большая ее порция досталась подсистеме автодополнения. Вот таким можно сделать дополнение имен файлов:
zsh menu completion
(выбрать нужный вариант можно табом по старинке, курсорными клавишами или стандартными emacs-хоткеями)

А вот так – дополнение опций:

Еще одна моя любимая магическая штуковина в автодополнении выглядит так: допустим, нужно подправить файл /usr/local/etc/rc.d/mysql. Пользователь bash бы ввел такую команду:

vim /usr/l[TAB]/e[TAB]/r[TAB]/m[TAB]

В zsh все несколько проще, а именно:

vim /u/l/e/r/m[TAB]

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

Ну вот, я вам передал примерно 0.65 процента магии zsh. Помимо автодополнения, ее залежи находятся в подсистеме подстановок (man zshexpn), но там я сам не очень уверенно ориентируюсь. Все-таки одна из прелестей zsh заключается в том, что мне необязательно учиться им пользоваться – для начала можно ограничиться только bash-совместимым подмножеством функций, регулярно натыкаясь на приятные мелочи в реализации привычных вещей.

Дальнейшее чтение:
обзор zsh от Алексея Федорчука,
Собрание хаков и идиом zsh: zsh lovers.

Categories: Shell, Tips, Unix, Техноблог Tags: ,

Чудеса!!

June 6th, 2008 3 comments

Я страсть как люблю хакерские программки, которые удивляют самим фактом своего существования.

Одна из таких: тетрис на sed’е. Это что-то невероятное!

p.s. да, и я тоже, оказывается, шаблонно мыслю :)

Пятничная загогулина (bash)

April 11th, 2008 15 comments

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

#!/usr/bin/bash
echo "one two three" | read a b c
echo "<$a> <$b> <$c>"

Что в нем не так?

Я ожидаю увидеть два ответа. Первый — это просто переписать этот код так, чтобы он заработал. И второй ответ — опционально — объяснение, почему не работает в таком виде.

p.s. второго ответа я пока сам не знаю, поэтому буду с интересом ждать его от вас :)
p.p.s. ответивший верно, как всегда – умничка (-ца (маловероятно)).

UPD: На второй вопрос ответ уже есть:
gds
есть мнение, что переменные, прочитанные read, остаются в переменных “экземпляра” баша, запущенного для выполнения “read a b c”, и не попадают в родительский баш, запустивший “echo … | read a b c”.

gds’у – респект!
А я понял, что в следующий раз надо постить задачки посложнее..

UPD2 свое решение выложу сегодня в конце рабочего дня
UPD3

Кажется, я нечаянно сорвал рабочий день моего начальника, но зато он мне прислал вот такое остроумное решение:
str=`echo "one two three" | (read a b c; echo "a=$a; b=$b; c=$c;") `
eval "$str";
echo "<$a> <$b> <$c>"

Петя, ты отжог :)

Но на самом деле все это можно сделать несколько проще – через “here doc”:
read a b c <<<`echo "one two three"`
echo "<$a> <$b> <$c>"

Заговор от битых кластеров (добавляем информацию для восстановления архивов с помощью par2)

April 10th, 2008 15 comments

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

Итак, к делу: регулярно, при записывании данных на диск, остается некоторое количество свободного места. Лет 5 назад можно было положить диск на полочку, пометив, что еще 30 мегабайт можно забить каким-нибудь хламом, но сейчас стоимость болванки – 10 рублей, такой аргумент не действует. И, соответственно, привычку оставлять место “на потом” надо искоренять. Мне кажется, наиболее разумным было бы добавить на диск данные для восстановления – т.н. корректирующие коды Рида-Соломона, которые могут пригодится в случае, если диск будет поврежден.

Собственно весь заговор выглядит следующим образом:
#sudo aptitude install par2
#man par2
#cd backups
#ls
dump.sql.gz
#par2 create -v -r10 -n1 -m500 dump.sql.gz
#ls
dump.sql.gz dump.sql.gz.par2 dump.sql.gz.vol000+100.par2

Эта команда добавит 10% избыточной информации к данным, запишет все это в один файл, при этом программе par2 разрешено использовать 500 мегабайт оперативной памяти. Файлы *.par2 следует записать на диск вместе с дампом.

Мне эта программа понравилась, я захотел ее проверить в боевых условиях. Сделал архив размером около 400 Мб, добавил данные для восстановления – еще 200Мб – *.par2 файлы (50% избыточность, по умолчанию – 5%). Все это я записал на CD-RW, в котором потом сделал, простите, дырку. В итоге стандартными средствами удавалось прочитать только первые 150 Кб данных. Чтобы восстановить файл нужно сначала все считать пускай с ошибками – для этого есть программа dd_rescue, которая является практчески полным аналогом dd с одним исключением – она умеет игнорировать ошибки чтения:

диск с дыркой

#sudo dd_rescue -Av -b 1048576 -B 1048576 /dev/scd0 brokencd.iso(-A – заполняь нулями те участки файла, которые считать не удалось, v – verbose, -b – размер блока данных, -B – размер блока данных для проблемных областей диска)
# sudo mount -o loop brokencd.iso mnt # монтируем получившийся образ диска
# cp mnt/* dump; cd dump # копируем содержимое
# par2 r archive.par2 # приводим в изначальный вид

На этом эксперимент завершился – все данные с диска восстановлены. Даже скучно.
Но пример, мне кажется, весьма красноречив :)