<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Юникс и другие &#187; *NIX</title>
	<atom:link href="http://boombick.org/blog/posts/category/nix/feed" rel="self" type="application/rss+xml" />
	<link>http://boombick.org/blog</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Tue, 29 Nov 2011 22:14:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Апгрейд notify-send</title>
		<link>http://boombick.org/blog/posts/201</link>
		<comments>http://boombick.org/blog/posts/201#comments</comments>
		<pubDate>Sat, 08 Jan 2011 18:30:21 +0000</pubDate>
		<dc:creator>boombick</dc:creator>
				<category><![CDATA[*NIX]]></category>

		<guid isPermaLink="false">http://boombick.org/blog/?p=201</guid>
		<description><![CDATA[Есть у меня одна развлекуха &#8211; люблю я всяческие мудрости, афоризмы, цитаты etc. Нравится мне мудрость, ужатая в короткую фразу (это, в частности, можно заметить и по предыдущему посту). И недавно наткнулся я на ресурс с афоризмами &#8211; Forismatic.com на котором этих цитат видимо-невидимо. Но вся прелесть в том, что у этого сервиса есть API, [...]]]></description>
			<content:encoded><![CDATA[<p>Есть у меня одна развлекуха &#8211; люблю я всяческие мудрости, афоризмы, цитаты etc. Нравится мне мудрость, ужатая в короткую фразу (это, в частности, можно заметить и по <a href="http://boombick.org/blog/posts/198">предыдущему посту</a>). И недавно наткнулся я на ресурс с афоризмами &#8211; <a href="http://ru.forismatic.com">Forismatic.com</a> на котором этих цитат видимо-невидимо. Но вся прелесть в том, что у этого сервиса есть <a href="http://ru.forismatic.com/api/">API</a>, позволяющее тянуть афоризмы с их сервиса в нескольких удобных форматах. И захотелось мне раз в 10 минут наблюдать эти афоризмы на своем десктопе<br />
<span id="more-201"></span><br />
Решение, конечно же, очевидно &#8211; notify-send. Но. Оказалось, что &#8220;ванильная&#8221; сборка обладает рядом болезней: например нет никакой возможности повлиять на размер сообщения (и из-за этого длинные цитаты показывались обрезанными) и совершенно игнорирует свой параметр <code>-t</code>, из-за чего месседжи висят по 10 секунд и успевают надоесть :)</p>
<p>Несколько минут гугления помогли решить проблему. Итак:<br />
Всё нижеописанное делалось на ubuntu 10.04, но, я думаю, не будет никаких проблем повторить все это для любого дистрибутива.<br />
Для начала добавляем репозиторий с патченной notify-osd и заменяем ей родную</p>
<blockquote><pre>
sudo add-apt-repository ppa:leolik/leolik
</pre>
</blockquote>
<p>В этой версии вылечены болезни, о которых я писал выше. Параметр <code>-t</code> заработал, а управлять видом сообщения стало можно через конфиг.<br />
Обновляем список пакетов и заменяем notify-osd</p>
<blockquote><pre>
sudo aptitude update &#038;&#038; sudo aptitude install notify-osd
</pre>
</blockquote>
<p>Создаем в домашней директории файлик <code>.notify-osd</code> с примерно следующим содержанием:</p>
<blockquote><pre>
slot-allocation = fixed
bubble-expire-timeout = 10sec
bubble-vertical-gap = 5px
bubble-horizontal-gap = 5px
bubble-corner-radius = 37,5%
bubble-icon-size = 30px
bubble-gauge-size = 6px
bubble-width = 400px
bubble-background-color = 222222
bubble-background-opacity = 90%
text-margin-size = 10px
text-title-size = 100%
text-title-weight = bold
text-title-color = ffffff
text-title-opacity = 100%
text-body-size = 90%
text-body-weight = normal
text-body-color = eaeaea
text-body-opacity = 100%
text-shadow-opacity = 100%
</pre>
</blockquote>
<p>Полное описание параметров вы можете найти по ссылке в конце поста. Нас интересует параметр <code>bubble-width</code>, увеличив который, я смог таки впихнуть в сообщение большинство цитат :)</p>
<p>Затем осталось добавить все это в <code>cron</code> и наслаждаться жизнью :)<br />
Добавляем в <code>cron</code> команду</p>
<blockquote><pre>
*/10 * * * * env DISPLAY=:0 /usr/bin/notify-send -t 5000 -i /home/boombick/.config/webdev-info-icon.png -u normal "`/usr/bin/wget -qO - 'http://api.forismatic.com/api/1.0/?method=getQuote&#038;key=${RANDOM}&#038;format=text&#038;lang=ru'`"
</pre>
</blockquote>
<p>Время показа сообщения указывается в миллисекундах. В моем примере таймаут равен 5 секундам. Параметр <code>-i</code> добавляет иконку к сообщению. Вот иконка, которую использовал я:<br />
<a href="http://boombick.org/blog/wp-content/uploads/2011/01/webdev-info-icon.png"><img src="http://boombick.org/blog/wp-content/uploads/2011/01/webdev-info-icon.png" alt="" title="webdev-info-icon" width="128" height="128" class="alignnone size-full wp-image-204" /></a><br />
Вы можете выбрать ту, которая вам больше понравится. В API Foristmatic используется странный параметр key, который каким-то образом влияет на показ цитаты. Никакой закономерности я не нашел и просто впихнул туда RANDOM =)<br />
И вот что получилось:<br />
<a href="http://boombick.org/blog/wp-content/uploads/2011/01/quote.png"><img src="http://boombick.org/blog/wp-content/uploads/2011/01/quote.png" alt="" title="quote" width="418" height="183" class="alignnone size-full wp-image-202" /></a></p>
<p>Это самый примитивный способ, простор для фантазии есть :) Можно считать длину текста, править конфиг на лету, показывать сообщение и возвращать все на место. Потому как очень длинные афоризмы все-таки обрезаются. Можно вставить рандомное переключение языка ru|en, чтобы смотреть цитаты еще и на английском. Можно еще что-нибудь придумать и я обязательно этим займусь :) А если вы придумаете что-нибудь интересное &#8211; присылайте, патчи с удовольствием принимаются :)</p>
<p>Ссылки по теме:<br />
Описание конфигурации notify-osd <a href="http://leolik.blogspot.com/2009/12/notify-osd.html">http://leolik.blogspot.com/2009/12/notify-osd.html</a><br />
Дополнительный тюнинг notify-send <a href="http://leolik.blogspot.com/2010/07/notify-osd.html">http://leolik.blogspot.com/2010/07/notify-osd.html</a><br />
Описание API Forismatic <a href="http://ru.forismatic.com/api/">http://ru.forismatic.com/api/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://boombick.org/blog/posts/201/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Тестируем MariaDB</title>
		<link>http://boombick.org/blog/posts/99</link>
		<comments>http://boombick.org/blog/posts/99#comments</comments>
		<pubDate>Wed, 26 May 2010 14:33:09 +0000</pubDate>
		<dc:creator>boombick</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://boombick.org/blog/posts/99</guid>
		<description><![CDATA[На недавно прошедшей DevConf выступал с докладом Michael &#8220;Monty&#8221; Widenius, автор и идейный вдохновитель MySQL. Он рассказал про то, что Oracle потихоньку убивает MySQL и презентовал форк под названием MariaDB. Меня заинтересовала эта СУРБД и вот представляю вам свой опыт ее использования :) Итак, по шагам. Эксперементировать решил на Debian, коий и поднял в виртуальной [...]]]></description>
			<content:encoded><![CDATA[<p>На недавно прошедшей <a href="http://devconf.ru">DevConf</a> выступал с докладом <a href="http://en.wikipedia.org/wiki/Michael_Widenius">Michael &#8220;Monty&#8221; Widenius</a>, автор и идейный вдохновитель MySQL. Он рассказал про то, что Oracle потихоньку убивает MySQL и презентовал форк под названием <a href="http://askmonty.org/wiki/MariaDB_versus_MySQL">MariaDB</a>.<br />
Меня заинтересовала эта СУРБД и вот представляю вам свой опыт ее использования :)<br />
<span id="more-99"></span><br />
Итак, по шагам.<br />
Эксперементировать решил на Debian, коий и поднял в виртуальной машине. Меня, в первую очередь, интересовало ее применение на собственных проектах и совместимость с моими скриптами и сайтиками :)<br />
Итак, сначала выполняем следующие действия:</p>
<p>Добавляем ключ репозитория в хранилище и добавляем репозиторий в sources.list</p>
<blockquote><pre>
wget -O- http://ourdelta.org/deb/ourdelta.gpg | sudo apt-key add -
    sudo wget http://ourdelta.org/deb/sources/lenny-mariadb-ourdelta.list \
      -O /etc/apt/sources.list.d/ourdelta.list
</pre>
</blockquote>
<p>Затем устанавливаем, собственно, сервер и клиентскую либу. Все остальное, что нам будет нужно, потянется по зависимостям</p>
<blockquote><pre>
aptitude install libmariadbclient16 mariadb-server-5.1
 </pre>
</blockquote>
<p><a href='http://boombick.org/blog/wp-content/uploads/2010/05/password_setup.png' title='password_setup.png'><img src='http://boombick.org/blog/wp-content/uploads/2010/05/password_setup.png' alt='password_setup.png' /></a><br />
Все, как в mysql :) Вводим желаемый пароль root для входа в mariadb</p>
<p><a href='http://boombick.org/blog/wp-content/uploads/2010/05/login.png' title='login.png'><img src='http://boombick.org/blog/wp-content/uploads/2010/05/login.png' alt='login.png' /></a><br />
Затем логинимся</p>
<blockquote><pre>
mysql -u root -p
</pre>
</blockquote>
<p>Все до боли привычно и знакомо :)<br />
Ну чтож, пока все отлично (даже запускается как /etc/init.d/mysql start), проверим, как оно дружит с PHP</p>
<p>Сначала я хотел запустить стандартные бенчмарки, но жестоко обломался :) В репозитории были версии только для 64-битных систем<br />
<a href='http://boombick.org/blog/wp-content/uploads/2010/05/test_failed.png' title='test_failed.png'><img src='http://boombick.org/blog/wp-content/uploads/2010/05/test_failed.png' alt='test_failed.png' /></a></p>
<p>Ну и фиг с ним, подрубаем PHP</p>
<blockquote><pre>
aptitude install php5-cli php5-mysql
</pre>
</blockquote>
<p>создаем тестовую табличку<br />
<a href='http://boombick.org/blog/wp-content/uploads/2010/05/create_table.png' title='create_table.png'><img src='http://boombick.org/blog/wp-content/uploads/2010/05/create_table.png' alt='create_table.png' /></a><br />
и проверяем</p>
<p><a href='http://boombick.org/blog/wp-content/uploads/2010/05/test_connect.png' title='test_connect.png'><img src='http://boombick.org/blog/wp-content/uploads/2010/05/test_connect.png' alt='test_connect.png' /></a></p>
<p><a href='http://boombick.org/blog/wp-content/uploads/2010/05/test_connect_result.png' title='test_connect_result.png'><img src='http://boombick.org/blog/wp-content/uploads/2010/05/test_connect_result.png' alt='test_connect_result.png' /></a></p>
<p>Как видите, со стороны PHP все абсолютно прозрачно и никаких лишних телодвижений совершать не приходится. Это радует :)<br />
Для эксперимента можно поставить Wordpres<br />
Доставляем apache и все необходимое для него и пробуем<br />
<a href='http://boombick.org/blog/wp-content/uploads/2010/05/wp_install.png' title='wp_install.png'><img src='http://boombick.org/blog/wp-content/uploads/2010/05/wp_install.png' alt='wp_install.png' /></a></p>
<p><a href='http://boombick.org/blog/wp-content/uploads/2010/05/wp_installed.png' title='wp_installed.png'><img src='http://boombick.org/blog/wp-content/uploads/2010/05/wp_installed.png' alt='wp_installed.png' /></a></p>
<p>Все отлично :)</p>
<p>PS Моей целью не было выяснение всех отличий MariaDB от MySQL, меня интересовала именно возможность применять ее в собственных проектах и дальнейшего отказа от MySQL. Возможность проверил, в дальнейшем попробую поставить ее на реальный сервер и попробовать в  production на каких-нибудь не очень критичных проектах :)<br />
О результатх будет отдельный пост.</p>
]]></content:encoded>
			<wfw:commentRss>http://boombick.org/blog/posts/99/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Консольные хитрости #2</title>
		<link>http://boombick.org/blog/posts/98</link>
		<comments>http://boombick.org/blog/posts/98#comments</comments>
		<pubDate>Mon, 24 May 2010 15:33:22 +0000</pubDate>
		<dc:creator>boombick</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://boombick.org/blog/posts/98</guid>
		<description><![CDATA[Продолжаем публикацию &#8220;однострочников&#8221; для bash, которые выполняют полезные и интересные действия :) Список установленных расширений для Firefox grep -hIr -m 1 em:name ~/.mozilla/firefox/*.default/extensions&#124;sed 's#\s*##'&#124;tr '=' '"""'&#124;cut -f3 -d'"'&#124;sort -u Список установленных расширений для Chromium (с адресом страницы) for i in $(find ~/.config/chromium/*/Extensions -name 'manifest.json'); do n=$(grep -hIr name $i&#124; cut -f4 -d '"'&#124; sort);u="https://chrome.google.com/extensions/detail/";ue=$(basename $(dirname [...]]]></description>
			<content:encoded><![CDATA[<p>Продолжаем публикацию &#8220;однострочников&#8221; для bash, которые выполняют полезные и интересные действия :)<br />
<span id="more-98"></span><br />
Список установленных расширений для Firefox</p>
<blockquote><pre>
grep -hIr -m 1 em:name ~/.mozilla/firefox/*.default/extensions|sed 's#\s*##'|tr '<>=' '"""'|cut -f3 -d'"'|sort -u
</pre>
</blockquote>
<p>Список установленных расширений для Chromium (с адресом страницы)</p>
<blockquote><pre>
for i in $(find ~/.config/chromium/*/Extensions -name 'manifest.json'); do n=$(grep -hIr name $i| cut -f4 -d '"'| sort);u="https://chrome.google.com/extensions/detail/";ue=$(basename $(dirname $(dirname $i))); echo -e "$n:\n$u$ue\n" ; done
</pre>
</blockquote>
<p>Уровень сигнала wifi</p>
<blockquote><pre>
/sbin/iwconfig wlan0 | grep Quality | cut -d = -f2 | awk '{print $1}'
</pre>
</blockquote>
<p>Оптимизация sqlite-баз, в которых Firefox хранит всякую служебную информацию. Позволяет немного ускорить его работу</p>
<blockquote><pre>
find ~/.mozilla/firefox -name '*.sqlite' -print -exec sqlite3 {} "VACUUM; REINDEX;" \;
</pre>
</blockquote>
<p>Количество процессов для пользователя (Linux only)</p>
<blockquote><pre>
pgrep -cu boombick
</pre>
</blockquote>
<p>Сравнить вывод двух команд</p>
<blockquote><pre>
diff <(tail -10 file1) <(tail -10 file2)
</pre>
</blockquote>
<p>Удалить все файлы, кроме одного :) Часто пригождается, чтобы не писать rm тут_куча-имен-файлов</p>
<blockquote><pre>
ls -Q | grep -v "not-for-delete-file" | xargs rm -r
</pre>
</blockquote>
<p>Собрать несколько тарболлов в один</p>
<blockquote><pre>
cat 1.tar.gz 2.tar.gz | tar zxvif -
</pre>
</blockquote>
<p>Размер окна терминала</p>
<blockquote><pre>
 echo $COLUMNS x $LINES
</pre>
</blockquote>
<p>Вывести man-страницу как обычный текст. Удобно для распечатки</p>
<blockquote><pre>
man need-man | col -bx
</pre>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://boombick.org/blog/posts/98/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Установка Django на devio.us</title>
		<link>http://boombick.org/blog/posts/95</link>
		<comments>http://boombick.org/blog/posts/95#comments</comments>
		<pubDate>Tue, 04 May 2010 08:02:31 +0000</pubDate>
		<dc:creator>boombick</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://boombick.org/blog/posts/95</guid>
		<description><![CDATA[Как, наверняка, всем известно, недавно появился проект Devio.us, который предлагает всем желающим бесплатный shell-хостинг на базе OpenBSD. В нагрузку к шеллу также предлагается домен третьего уровня, вида %username%.devio.us или devio.us/~%username%, одна база данных MySQL и 100 мегов места. За пару баксов в месяц эти показатели можно улучшить :) На сервере установлен PHP (версии 5.2.12) как [...]]]></description>
			<content:encoded><![CDATA[<p>Как, наверняка, всем известно, недавно появился проект <a href="http://devio.us">Devio.us</a>, который предлагает всем желающим бесплатный shell-хостинг на базе OpenBSD. В нагрузку к шеллу также предлагается домен третьего уровня, вида %username%.devio.us или devio.us/~%username%, одна база данных MySQL и 100 мегов места. За пару баксов в месяц эти показатели можно улучшить :)<br />
На сервере установлен PHP (версии 5.2.12) как модуль апача (весьма, кстати, древнего &#8211; 1.3.29) и предлагается CGI-интерфейс. Ну и также доступны perl 5.10.1 и python 2.5.4. Целью проекта является привлечение новых членов в коммьюнити OpenBSD. При регистрации необходимо указать причину, по которой вам кровь из носу надо получить там аккаунт :) Процент отказов, к слову, довольно мал.<br />
Итак, поигравшись с PHP, захотелось чего-то большего. И так как на сервере присутствует python, захотелось прикрутить туда Django.<br />
<span id="more-95"></span><br />
<strong>Установка Django</strong><br />
Проведя ревизию модулей apache я выяснил, что ни mod_python, ни mod_wsgi не установлены. Грустно, но ладно. Для начала я просто залил туда дистрибутив django (версии 1.1.1)</p>
<blockquote>
<pre>
$ scp Django-1.1.1.tar.gz devio.us:</pre>
</blockquote>
<p>и распаковал его</p>
<blockquote>
<pre>
$ gunzip Django-1.1.1.tar.gz
$ tar xvf Django-1.1.1.tar
$ ln -s Django-1.1.1 django #  для дальнейшего удобства</pre>
</blockquote>
<p>Добавим переменную окружения PYTHONPATH для корректной работы Django</p>
<blockquote>
<pre>
$ export PYTHONPATH='/home/boombick/django'
$ echo "export PYTHONPATH='/home/boombick/django'" &gt;&gt; ~/.profile</pre>
</blockquote>
<p>И создадим симлинк для django-admin</p>
<blockquote>
<pre>
$ mkdir ~/bin
$ ln -s /home/boombick/django/django/bin/django-admin.py /home/boombik/bin/django-admin.py</pre>
</blockquote>
<p>Дальше все просто: создаем новый проект Django</p>
<blockquote>
<pre>
$ django-admin.py startproject djtest
$ cd djtest</pre>
</blockquote>
<p>И на этом этапе я просто запустил dev-сервер из поставки Django на высоком порту (занять порт с номером ниже 1024 без привелегий root не получится)</p>
<blockquote>
<pre>
$ python manage.py runserver 0.0.0.0:32000</pre>
</blockquote>
<p>Зайдя на http://boombick.devio.us:32000 я увидел приветственную страницу пустого проекта Django. Все получилось :)</p>
<p><strong>Запуск Django через CGI</strong><br />
В принципе, можно было бы оставить все и так. Но.<br />
1. Хотелось все-таки ходить к себе на страничку по 80 порту<br />
2. На free-аккаунте нельзя детачить приложения. Т.е. нельзя оставить запущенным сервер и разлогиниться. Что, впрочем, логично, иначе сервер превратился бы в рассадник IRC-ботов :)<br />
Можно, конечно, извратиться и держать логин постоянно, восстанавливая оборванное подключение и перезапуская сервер, но это не наш путь.</p>
<p>Итак.<br />
Сначала я просто пробрасывал запросы к Django через PHP (в виде index.php) :) Эдакий PHP-Proxy, но мало того, что это запредельно криво, так еще и не очень понятно, что делать с POST-запросами. Выход был один &#8211; заставить Django работать через CGI.<br />
Помучив гугл я нашел несколько разноненных мануалов и приступил к выполнению.<br />
Для начала создадим в директории <code>$HOME/public_html</code> файл django.cgi вот с таким содержанием:</p>
<blockquote>
<pre>
#!/usr/local/bin/python
# encoding: utf-8
"""
django.cgi

A simple cgi script which uses the django WSGI to serve requests.
Rewrited for use on devio.us shell hosting

Code copy/pasted from PEP-0333 and then tweaked to serve django.

http://www.python.org/dev/peps/pep-0333/#the-server-gateway-side

This script assumes django is on your sys.path, and that your site code is at
/home/mycode/mysite. Copy this script into your cgi-bin directory (or do
whatever you need to to make a cgi script executable on your system), and then
update the paths at the bottom of this file to suit your site.

This is probably the slowest way to serve django pages, as the python
interpreter, the django code-base and your site code has to be loaded every
time a request is served. FCGI and mod_python solve this problem, use them if
you can.

In order to speed things up it may be worth experimenting with running
uncompressed zips on the sys.path for django and the site code, as this can be
(theorectically) faster. See PEP-0273 (specifically Benchmarks).

http://www.python.org/dev/peps/pep-0273/

Make sure all python files are compiled in your code base. See

http://docs.python.org/lib/module-compileall.html

"""

import os, sys
sys.path.append("/home/boombick/django") # Поменяйте на путь к Django
sys.path.append("/home/boombick/djtest")  # Поменяйте на путь к вашему проекту

import django.core.handlers.wsgi

def run_with_cgi(application):

    environ                      = dict(os.environ.items())
    environ['wsgi.input']        = sys.stdin
    environ['wsgi.errors']       = sys.stderr
    environ['wsgi.version']      = (1,0)
    environ['wsgi.multithread']  = False
    environ['wsgi.multiprocess'] = True
    environ['wsgi.run_once']     = True

    if environ.get('HTTPS','off') in ('on','1'):
        environ['wsgi.url_scheme'] = 'https'
    else:
        environ['wsgi.url_scheme'] = 'http'

    headers_set  = []
    headers_sent = []

    def write(data):
        if not headers_set:
             raise AssertionError("write() before start_response()")

        elif not headers_sent:
             # Before the first output, send the stored headers
             status, response_headers = headers_sent[:] = headers_set
             sys.stdout.write('Status: %s\r\n' % status)
             for header in response_headers:
                 sys.stdout.write('%s: %s\r\n' % header)
             sys.stdout.write('\r\n')

        sys.stdout.write(data)
        sys.stdout.flush()

    def start_response(status,response_headers,exc_info=None):
        if exc_info:
            try:
                if headers_sent:
                    # Re-raise original exception if headers sent
                    raise exc_info[0], exc_info[1], exc_info[2]
            finally:
                exc_info = None     # avoid dangling circular ref
        elif headers_set:
            raise AssertionError("Headers already set!")

        headers_set[:] = [status,response_headers]
        return write

    result = application(environ, start_response)
    try:
        for data in result:
            if data:    # don't send headers until body appears
                write(data)
        if not headers_sent:
            write('')   # send headers now if body was empty
    finally:
        if hasattr(result,'close'):
            result.close()

os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
run_with_cgi(django.core.handlers.wsgi.WSGIHandler())</pre>
</blockquote>
<p>Затем меняем в <code>/path/to/dajngo-project/settings.py</code> параметр <code>ROOT_URLCONF</code> на <code>urls</code> вместо <code>projectname.urls</code><br />
Делаем файл исполняемым</p>
<blockquote>
<pre>
$ chmod a+x public_html/django.cgi</pre>
</blockquote>
<p>И проверяем работоспособность :)</p>
<p>http://boombick.devio.us/django.cgi</p>
<p><a href="http://boombick.org/blog/wp-content/uploads/2010/05/djangocgi.png" title="djangocgi.png"><img src="http://boombick.org/blog/wp-content/uploads/2010/05/djangocgi.thumbnail.png" alt="djangocgi.png" /></a><br />
Если все ок, то можно переходить к следующему шагу. А если нет и вы получаете 500 ошибку, то смотрите лог. Который, кстати, лежит в <code>/var/www/logs/error_log</code> В процессе установки очень удобно было его мониторить в отдельной консольке при помощи <code>tail -f</code><br />
Учтите только, что в этот лог падают сообщения о всех ошибках и вам надо отделять свои запросы от остальных :)</p>
<p><strong>Настройка Apache</strong><br />
Теперь надо настроить Apache для переадресации всех запросов к нашему django.cgi. Я очень давно не ковырялся с Apache (в последнее время использую исключительно nginx) и с трудом и доками вспоминал синтаксис mod_rewrite<br />
В результате родился вот такой вот файлик <code>.htaccess</code>, который надо положить в директорию <code>public_html</code></p>
<blockquote>
<pre>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /django.cgi%{REQUEST_URI}?%{QUERY_STRING}</pre>
</blockquote>
<p><strong>Проверяем</strong><br />
В <code>~/djtest/urls.py</code> добавим правило для обработки всех адресов</p>
<blockquote>
<pre>
from django.conf.urls.defaults import *
from views import test_page

urlpatterns = patterns('',
    (r'^(.*)$', test_page)
)</pre>
</blockquote>
<p>И создадим файл <code>~/djtest/views.py</code> с, собственно, обработчиком</p>
<blockquote>
<pre>
from django.http import HttpResponse       

def test_page(request, url):
    html = "WORKING! Url is %s" % url
    return HttpResponse(html)</pre>
</blockquote>
<p>Заходим на http://boombick.devio.us/foo/bar<br />
<a href="http://boombick.org/blog/wp-content/uploads/2010/05/django.png" title="django.png"><img src="http://boombick.org/blog/wp-content/uploads/2010/05/django.thumbnail.png" alt="django.png" /></a><br />
Все работает :)</p>
<p><strong>Благодарности</strong><br />
Хочу сказать большое спасибо ребятам из конференции django@conference.jabber.ru, а конкретно <strong>ne_formal</strong> за неоценимую помощь :) Без него этот процесс затянулся бы куда больше!</p>
<p><strong>Важное замечание</strong><br />
Если вы читали комментарии в начале файла django.cgi, то не могли не заметить такой абзац:</p>
<blockquote><p>This is probably the slowest way to serve django pages, as the python<br />
interpreter, the django code-base and your site code has to be loaded every<br />
time a request is served. FCGI and mod_python solve this problem, use them if<br />
you can.
</p></blockquote>
<p>Что в вольном переводе выглядит как:<br />
<em>Это самый медленный путь для работы с django. На каждый запрос создается экземпляр интерпретатора Python. Если у вас есть возможность использовать FCGI или mod_python &#8211; используйте их!</em><br />
Так что статью прощу рассматривать исключительно как proof of concept или выход из совсем уж безвыходной ситуации! :)<br />
Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://boombick.org/blog/posts/95/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PROMPT в стиле MS-DOS</title>
		<link>http://boombick.org/blog/posts/91</link>
		<comments>http://boombick.org/blog/posts/91#comments</comments>
		<pubDate>Mon, 29 Mar 2010 17:49:57 +0000</pubDate>
		<dc:creator>boombick</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://boombick.org/blog/posts/91</guid>
		<description><![CDATA[Наткнулся на забавную фишку :) Делаем следующее export PS1="C:\$( pwd &#124; sed 's:/:\\\\\:g' )> " и ностальгируем по временам MS-DOS :) Если очень понравилось, то можно добавить в ~/.bashrc следующий код: PS1="C:\$( pwd &#124; sed 's:/:\\\\\:g' )> " и наслаждаться красотой постоянно :)]]></description>
			<content:encoded><![CDATA[<p>Наткнулся на забавную фишку :) Делаем следующее</p>
<blockquote><pre>export PS1="C:\$( pwd | sed 's:/:\\\\\:g' )> "</pre>
</blockquote>
<p>и ностальгируем по временам MS-DOS :)</p>
<p><a href='http://boombick.org/blog/wp-content/uploads/2010/03/screen.png' title='PROMPT в стиле MS-DOS'><img src='http://boombick.org/blog/wp-content/uploads/2010/03/screen.thumbnail.png' alt='PROMPT в стиле MS-DOS' /></a></p>
<p>Если очень понравилось, то можно добавить в <code>~/.bashrc</code> следующий код:</p>
<blockquote><pre>
PS1="C:\$( pwd | sed 's:/:\\\\\:g' )> "
</pre>
</blockquote>
<p>и наслаждаться красотой постоянно :)</p>
]]></content:encoded>
			<wfw:commentRss>http://boombick.org/blog/posts/91/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Консольные хитрости</title>
		<link>http://boombick.org/blog/posts/90</link>
		<comments>http://boombick.org/blog/posts/90#comments</comments>
		<pubDate>Sun, 28 Feb 2010 08:18:35 +0000</pubDate>
		<dc:creator>boombick</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://boombick.org/blog/posts/90</guid>
		<description><![CDATA[Опытные юниксоиды знают и осознают всю мощь использования командной строки и немного &#8220;свысока&#8221; посматривают на &#8220;мышевозов&#8221; :) Но и в консоли есть свои недостатки, которые побеждаются с помощью каких-то приемов. У каждого свой набор, а я хочу поделиться своими наработками-находками-привычками, которые появились за долгие годы использования командной строки. Эдакий небольшой cheat-sheet. Начнем :) 1. Копирование [...]]]></description>
			<content:encoded><![CDATA[<p>Опытные юниксоиды знают и осознают всю мощь использования командной строки и немного &#8220;свысока&#8221; посматривают на &#8220;мышевозов&#8221; :) Но и в консоли есть свои недостатки, которые побеждаются с помощью каких-то приемов. У каждого свой набор, а я хочу поделиться своими наработками-находками-привычками, которые появились за долгие годы использования командной строки. Эдакий небольшой cheat-sheet.<br />
Начнем :)</p>
<p>1. Копирование файлов с указанием прогресса. Всегда чертовски не хватало информативности в <code>cp</code></p>
<blockquote>
<pre>
rsync --progress file1 file2</pre>
</blockquote>
<p><span id="more-90"></span></p>
<p>2. Преобразование текста в картинку. Использовал для создания простенькой капчи</p>
<blockquote>
<pre>
echo -e "Some Text Line1\nSome Text Line 2" | convert -background none -density 196  -resample 72 -unsharp 0x.5 -font "Courier" text:- -trim +repage -bordercolor white -border 3  text.gif</pre>
</blockquote>
<p>3. Поиск и замена в текстовых файлах</p>
<blockquote>
<pre>
find . -iname "FILENAME" -exec sed -i 's/SEARCH_STRING/REPLACE_STRING/g' {} \;</pre>
</blockquote>
<p>4. Метод Столлмана! Отправка веб-странички по почте :)</p>
<blockquote>
<pre>
{ u="http://twitter.com/boombick"; echo "Subject: $u"; echo "Mime-Version: 1.0"; echo -e "Content-Type: text/html; charset=utf-8\n\n"; curl $u ; } | sendmail recipient@example.com</pre>
</blockquote>
<p>5. Запись iso-файла на диск</p>
<blockquote>
<pre>
cdrecord -v speed=4 driveropts=burnfree dev=/dev/scd0 cd.iso</pre>
</blockquote>
<p>6. Ограничение канала для scp. В данном случае ограничен 10kbps</p>
<blockquote>
<pre>
scp -l10 boombick@srv02:/home/svnstat/* .</pre>
</blockquote>
<p>7. Скриншот на удаленной машине :) (С запущенными иксами конечно)</p>
<blockquote>
<pre>
DISPLAY=":0.0" import -window root screenshot.png</pre>
</blockquote>
<p>8. Качаем и сразу распаковываем :)</p>
<blockquote>
<pre>
wget -qO - http://example.com/path/to/blah.tar.gz | tar xzf -</pre>
</blockquote>
<p>9. url_encode :) Достаточно примитивно, но часто помогает</p>
<blockquote>
<pre>
echo "$url" | sed 's/%/%25/g;s/ /%20/g;s/!/%21/g;s/"/%22/g;s/#/%23/g;s/\$/%24/g;s/\&amp;/%26/g;s/'\''/%27/g;s/(/%28/g;s/)/%29/g'</pre>
</blockquote>
<p>10. Погода в Москве :) Подставьте свой город</p>
<blockquote>
<pre>
curl -s "http://www.google.com/ig/api?weather=Moscow" | sed 's|.*&lt;temp_c data="\([^"]*\)"/&gt;.*|\1|'</pre>
</blockquote>
<p>Пока все, to be continued</p>
]]></content:encoded>
			<wfw:commentRss>http://boombick.org/blog/posts/90/feed</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Advanced grep</title>
		<link>http://boombick.org/blog/posts/88</link>
		<comments>http://boombick.org/blog/posts/88#comments</comments>
		<pubDate>Wed, 24 Feb 2010 12:48:17 +0000</pubDate>
		<dc:creator>boombick</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://boombick.org/blog/posts/88</guid>
		<description><![CDATA[Написал небольшой скриптик, который красиво форматирует результаты рекурсивного поиска по исходникам (вообще-то по любым файлам, но я писал это все именно для поиска по дереву исходников :)) Вот так выглядят результаты его работы &#8211; это поиск слова &#8216;function&#8217; по всем файлам во всех вложенных подпапках Как видно на скрине, результаты поиска группируются по файлам, показывается [...]]]></description>
			<content:encoded><![CDATA[<p>Написал небольшой скриптик, который красиво форматирует результаты рекурсивного поиска по исходникам (вообще-то по любым файлам, но я писал это все именно для поиска по дереву исходников :))<br />
<span id="more-88"></span><br />
Вот так выглядят результаты его работы &#8211; это поиск слова &#8216;function&#8217; по всем файлам во всех вложенных подпапках<br />
<a href="http://boombick.org/blog/wp-content/uploads/2010/02/screen.png" title="screen.png"><img src="http://boombick.org/blog/wp-content/uploads/2010/02/screen.thumbnail.png" alt="screen.png" /></a><br />
Как видно на скрине, результаты поиска группируются по файлам, показывается на какой строке файла найдено совпадение, сама искомая строка подсвечивается.<br />
Поиск регистронезависимый.</p>
<p>@FIXME<br />
При подсветке слова регистр слова сбрасывается</p>
<p>@TODO<br />
Сделать разбивку результатов по страницам<br />
Вынести настройки в конфиг (например такие, как цвет в результатах поиска)</p>
<p>Для работы использует bash, awk, grep, sed.<br />
В скрипте есть такая строка</p>
<blockquote>
<pre>
grep -vE '(svn|jquery)'</pre>
</blockquote>
<p>Это, собственно, исключения, которые надо выбрасывать из результатов поиска. Т.е. строки, в которых эти &#8220;буквосочетания&#8221; есть, в результаты не попадут. Если вам это не нужно, просто выкиньте эту часть (в последствии это тоже уйдет в конфиг) :)</p>
<p>Изначально все писалось для FreeBSD, посему если у вас bash установлен не по пути <code>/usr/local/bin/bash</code>, то либо поменяйте путь к интерпретатору, либо сделайте симлинк :)</p>
<p>Скрипт распространяется под BSD-лицензией, о багах пишите сюда :)<br />
Скачать: <a href="http://code.google.com/p/srch/">http://code.google.com/p/srch/</a><br />
Вот, вообщем-то, и все, enjoy! Надеюсь, кому-нибудь пригодится :)<br />
UPD: Спасибо за совет с размещением на GoogleCode!</p>
]]></content:encoded>
			<wfw:commentRss>http://boombick.org/blog/posts/88/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Немного о mod_perl</title>
		<link>http://boombick.org/blog/posts/83</link>
		<comments>http://boombick.org/blog/posts/83#comments</comments>
		<pubDate>Thu, 01 Oct 2009 13:18:24 +0000</pubDate>
		<dc:creator>boombick</dc:creator>
				<category><![CDATA[Debian]]></category>
		<category><![CDATA[web-servers]]></category>

		<guid isPermaLink="false">http://boombick.org/blog/posts/83</guid>
		<description><![CDATA[Apache &#8211; это очень популярный и широко используемый web-сервер. Есть множество альтернатив, но по возможностям настройки, гибкости и количеству доступных расширений Apache прочно держится в топе. В этой небольшой статье я расскажу как можно контролировать фактически все аспекты работы вашего web-сервера при помощи Perl и mod_perl mod_perl &#8211; это обычный модуль для Apache, который устанавливается [...]]]></description>
			<content:encoded><![CDATA[<p>Apache &#8211; это очень популярный и широко используемый web-сервер. Есть множество альтернатив, но по возможностям настройки, гибкости и количеству доступных расширений Apache прочно держится в топе. В этой небольшой статье я расскажу как можно контролировать фактически все аспекты работы вашего web-сервера при помощи Perl и <code>mod_perl</code><br />
<span id="more-83"></span><br />
<code>mod_perl</code> &#8211; это обычный модуль для Apache, который устанавливается также, как и все остальные модули. Но ключевое отличие в том, что этот модуль содержит в себе встроенный интерпретатор Perl, с помощью которого можно писать расширения и управлять фактически всеми аспектами работы сервера. Даже если вы никогда не писали (и не собираетесь писать) расширений для сервера, <code>mod_perl</code> пригодится вам чтобы, например, ускорить работу CGI-скриптов. А сам процесс описан ниже</p>
<p><b>Установка <code>mod_perl</code></b><br />
Все примеры показаны для ОС Linux Debian<br />
Устанавливаем пакет libapache2-mod-perl2</p>
<blockquote><pre>
lenny:~# apt-get install libapache2-mod-perl2
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  libapache2-reload-perl libbsd-resource-perl libperl5.10
The following NEW packages will be installed
  libapache2-mod-perl2 libapache2-reload-perl libbsd-resource-perl libperl5.10
0 upgraded, 4 newly installed, 0 to remove and 2 not upgraded.
Need to get 1201kB of archives.
After this operation, 3891kB of additional disk space will be used.
...
Processing triggers for man-db ...
Setting up libperl5.10 (5.10.0-19) ...
Setting up libapache2-mod-perl2 (2.0.4-5) ...
Enabling module perl.
Run '/etc/init.d/apache2 restart' to activate new configuration!
Setting up libapache2-reload-perl (0.10-2) ...
Setting up libbsd-resource-perl (1.28-1+b1) ...
</pre>
</blockquote>
<p>Как можно увидеть, модуль уже активирован.. Но никто не мешает сделать это еще раз (для надежности :) ) Или, например, после изменения конфигурации сервера, да и вообще, чтобы убедиться</p>
<blockquote><pre>lenny:~# a2enmod perl
Module perl already enabled
lenny:~# /etc/init.d/apache2 restart
Restarting web server: apache2 ... waiting .
</pre>
</blockquote>
<p>Модуль установлен, давайте займемся его настройкой. Самое простое &#8211; это добавить хендлер <code>perl-status</code> и посмотреть, что же происходит с нашим сервером. Создайте файл <code>/etc/apache2/conf.d/perl-status</code> со следующим содержимым:</p>
<blockquote><pre>
 #
 # make status information available at
 #   http://example.com/perl-status/
 #
 &lt;Location /perl-status&gt;
    SetHandler perl-script
    PerlHandler +Apache2::Status
&lt;/Location&gt;

 #
 # But only from the local host, and our trusted
 # remote IP.
 #
 &lt;Location /perl-status&gt;
    order deny,allow
    deny from all
    allow from 127.0.0.1
    allow from your.ip.address
&lt;/Location&gt;
</pre>
</blockquote>
<p>Перезапустите сервер и зайдите на адрес /perl-status. Узнаете несколько интересных вещей об окружении сервера и о загруженных модулях Perl<br />
<em><strong>Внимание!</strong></em> Эта информация содержит много такого, что не стоило бы показывать всем и каждому. Поэтому не стоит делать ее доступной для всех. Ограничьте доступ!</p>
<p><b>Ускорение Perl CGI-скриптов</b><br />
Так как <code>mod_perl</code> уже содержит встроенный интерпретатор Perl, то мы можем использовать его для запуска CGI-скриптов, вместо вызова внешней команды. Это позволит снизить накладные расходы на вызов отдельной копии интерпретатора при поступлении запроса на обработку скрипта. Есть способы добиться более внушительного ускорения, но это потребует внесения изменений в исходный код сценариев. В Debian CGI-скрипты по умолчанию располагаются в <code>/usr/lib/cgi-bin</code> Мы укажем Apache, что хотели бы запускать встроенный интерпретатор вместо внешнего для сценариев из этой директории.</p>
<blockquote><pre>
  PerlModule Apache::Registry
  Alias /cgi-bin/ /usr/lib/cgi-bin
  &lt;Location /cgi-bin&gt;
    SetHandler perl-script
    PerlHandler Apache::Registry
    PerlSendHeader On
    Options +ExecCGI
  &lt;/Location&gt;
</pre>
</blockquote>
<p>Перезапустите сервер (<code>/etc/init.d/apache2 restart</code>) и посмотрите, насколько быстрее стали работать скрипты :)</p>
<p><b>Загрузка модулей</b><br />
Продолжим. Давайте напишем код, который Apache мог бы использовать в процессе обработки страницы и пересылки ее клиенту. Нам необходимо разместить этот код так, чтобы встроенный интерпретатор смог загрузить его. По умолчанию в путь для поиска уже включены большинство системных директорий, но я считаю, что имеет смысл расположить его в очевидном месте :) <code>/etc/apache2/perl</code> Для добавления директории в путь поиска добавьте следующую директиву в <code>/etc/apache2/conf/00-mod-perl</code></p>
<blockquote><p>
#<br />
#  Load the startup script<br />
#<br />
PerlRequire /etc/apache2/perl/startup.pl</p>
</blockquote>
<p>Теперь при старте севера будет запускаться указанный скрипт. Давайте создадим его и поместим туда вот такой код</p>
<blockquote><p>
#<br />
#  Add /etc/apache2/perl to the mod_perl search path.<br />
#<br />
use lib  qw( /etc/apache2/perl );</p>
<p>#<br />
#  This script had no errors (?!)<br />
#<br />
1;
</p></blockquote>
<p>После перезапуска сервера путь для поиска будет обновлен и будет включать в себя нужную нам директорию.</p>
<p><b>Сделаем что-то полезное?</b><br />
Очень часто я вижу на своих проектах &#8220;пауков&#8221;, которые методично обшаривают страницу за страницей, качая содержимое. Вообщем я не возражаю против &#8220;зеркалирования&#8221; своих сайтов, но пока это все происходит незаметно для меня, в один поток и без съедания львиной доли ресурсов. А плохие &#8220;пауки&#8221; очень часто делают запросы, подобные следующим:</p>
<blockquote><p>
1.2.3.4 &#8211; [30/Apr/2009:19:36:29 +0100] &#8220;GET /articles/535#comment_2 HTTP/1.0&#8243;<br />
1.2.3.4 &#8211; [30/Apr/2009:19:36:30 +0100] &#8220;GET /articles/535#comment_3 HTTP/1.0&#8243;<br />
1.2.3.4 &#8211; [30/Apr/2009:19:36:30 +0100] &#8220;GET /articles/535#comment_5 HTTP/1.0&#8243;<br />
1.2.3.4 &#8211; [30/Apr/2009:19:36:31 +0100] &#8220;GET /articles/535#comment_4 HTTP/1.0&#8243;
</p></blockquote>
<p>Т.е. по якорям методично и многократно вытягивают одну и туже страницу, съедая ресурсы и трафик. Чтоже делать, будем их ловить с помощью вот такого модуля на Perl: <a href="http://boombick.org/DropClients.pm">DropClients</a><br />
Это сценарий на Perl, который обрабатывается <code>mod_perl</code>. Он выполняется для каждого входящего запроса и делает следующее:</p>
<ul>
<li>Выделяет из запроса IP-адрес и User-Agent</li>
<li>Если UA и IP &#8211; &#8220;плохие&#8221;, то отклоняет запрос</li>
<li>В нашем случае запрос отклоняется и тогда, когда в нем содержится &#8220;#&#8221;</li>
</ul>
<p>Если все хорошо, то запрос проходит</p>
<p>Чтобы запустить этот сценарий мы должны</p>
<ol>
<li>Загрузить его</li>
<li>И заставить его выполняться :)</li>
</ol>
<p>Сохраним модуль как <code>/etc/apache2/perl/DropClients.pm</code> и создадим файл <code>/etc/apache2/conf/dropclients</code> со следующим содержимым:</p>
<blockquote><p>
#<br />
#  Load the module<br />
#<br />
PerlModule DropClients</p>
<p>#<br />
#  Ensure it is invoked as an access handler<br />
#<br />
&lt;Location /&gt;<br />
     PerlAccessHandler DropClients<br />
&lt;/Location&gt;
</p></blockquote>
<p>После перезапуска метод <code>DropClients::request()</code> будет выполняться для каждого входящего запроса и нежелательные запросы будут отклоняться.</p>
<p>Нормальный запрос</p>
<blockquote><p>
user@notebook:~$ echo -e &#8220;GET / HTTP/1.0\n&#8221; | nc lenny 80 |grep ^HTTP<br />
HTTP/1.1 200 OK
</p></blockquote>
<p>&#8220;Плохой&#8221; запрос</p>
<blockquote><p>
user@notebook:~$ echo -e &#8220;GET /#foo HTTP/1.0\n&#8221; | nc lenny 80 |grep ^HTTP<br />
HTTP/1.1 403 Forbidden
</p></blockquote>
<p>Поскольку мы только что сделали &#8220;плохой&#8221; запрос, дальнейший доступ к серверу будет закрыт</p>
<blockquote><p>
user@notebook:~$ echo -e &#8220;GET / HTTP/1.0\n&#8221; | nc lenny 80 |grep ^HTTP<br />
HTTP/1.1 403 Forbidden
</p></blockquote>
<p>Если заглянете в код модуля, то увидите, что эта блокировка очень просто и снимается командой <code>rm -rf /tmp/blah</code></p>
<p><b>Различные типы обработчиков</b><br />
Для нашего модуля мы использовали обработчик <code>PerlAccessHandler</code>, который запускал скрипт при входящих соединениях. Но это лишь один из многих типов обработчиков. Есть также, например:</p>
<ul>
<li><code>PerlResponseHandler</code> &#8211; запускает сценарий после прохождения запроса</li>
<li><code>PerlOutputFilterHandler</code> &#8211; позволяет выполнить фильтрацию контента, отдаваемого пользователю (заменить слова, добавить футер&#8230; Сфера применения ограничена лишь вашей фантазией)</li>
</ul>
<p>Полный список обработчиков доступен в документации к <code>mod_perl</code> и <noindex><a href="http://perl.apache.org/docs/2.0/user/handlers/http.html">здесь</a></noindex> Там же можно найти и примеры кода</p>
]]></content:encoded>
			<wfw:commentRss>http://boombick.org/blog/posts/83/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>100 команд vim, которые должен знать каждый программист</title>
		<link>http://boombick.org/blog/posts/84</link>
		<comments>http://boombick.org/blog/posts/84#comments</comments>
		<pubDate>Tue, 29 Sep 2009 13:18:27 +0000</pubDate>
		<dc:creator>boombick</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://boombick.org/blog/posts/84</guid>
		<description><![CDATA[Небольшая подсказка по vim, будет полезна всем, я думаю. Это не руководство для начинающих (т.е. команд типа :wq здесь нет) Комментарии приветствуются :) Поиск /word Искать слово &#8220;word&#8221; сверху вниз ?word Искать слово &#8220;word&#8221; снизу вверх /jo[ha]n&#62; Искать &#8220;john&#8221; или &#8220;joan&#8221; /\&#60; the Искать слова, начинающееся на &#8220;the&#8221; /the\&#62; Искать слова, заканчивающиеся на &#8220;the&#8221; /\&#60; [...]]]></description>
			<content:encoded><![CDATA[<p>Небольшая подсказка по vim, будет полезна всем, я думаю. Это не руководство для начинающих (т.е. команд типа <code>:wq</code> здесь нет)<br />
Комментарии приветствуются :)<br />
<span id="more-84"></span></p>
<h2>Поиск</h2>
<table border="0" cellspacing="3">
<tr>
<td>/word</td>
<td>Искать слово &#8220;word&#8221; сверху вниз</td>
</tr>
<tr>
<td>?word</td>
<td>Искать слово &#8220;word&#8221; снизу вверх</td>
</tr>
<tr>
<td>/jo[ha]n&gt;</td>
<td>Искать &#8220;john&#8221; или &#8220;joan&#8221;</td>
</tr>
<tr>
<td>/\&lt; the</td>
<td>Искать слова, начинающееся на &#8220;the&#8221;</td>
</tr>
<tr>
<td>/the\&gt;</td>
<td>Искать слова, заканчивающиеся на &#8220;the&#8221;</td>
</tr>
<tr>
<td>/\&lt; the\&gt;</td>
<td>Искать &#8220;the&#8221;</td>
</tr>
<tr>
<td>/\&lt; …. \&gt;</td>
<td>Искать слова из четырех символов</td>
</tr>
<tr>
<td>/fred\|joe</td>
<td>Искать &#8220;fred&#8221; или &#8220;joe&#8221;</td>
</tr>
<tr>
<td>/\&lt;\d\d\d\d\&gt;</td>
<td>Искать 4 цифры подряд</td>
</tr>
<tr>
<td>/^\n\{3}</td>
<td>Искать 3 пустые строки</td>
</tr>
<tr>
<td>:bufdo /searchstr/</td>
<td>Искать во всех открытых файлах</td>
</tr>
</table>
<h2>Замена</h2>
<table border="0" cellspacing="3">
<tr>
<td>:%s/old/new/g</td>
<td>Заменить все вхождения &#8220;old&#8221; на &#8220;new&#8221;</td>
</tr>
<tr>
<td>:%s/old/new/gw</td>
<td>Заменить все вхождения &#8220;old&#8221; на &#8220;new&#8221;  с запросом подтверждения</td>
</tr>
<tr>
<td>:2,35s/old/new/g</td>
<td>Заменить все вхождения &#8220;old&#8221; на &#8220;new&#8221; между 2 и 35 строками</td>
</tr>
<tr>
<td>:5,$s/old/new/g</td>
<td>Заменить все вхождения &#8220;old&#8221; на &#8220;new&#8221; начиная с 5 строки и до конца файла</td>
</tr>
<tr>
<td>:%s/^/hello/g</td>
<td>Добавить &#8220;hello&#8221; в начало каждой строки</td>
</tr>
<tr>
<td>:%s/$/Harry/g</td>
<td>Добавить &#8220;Harry&#8221;  в конец каждой строки</td>
</tr>
<tr>
<td>:%s/onward/forward/gi</td>
<td>Заменить &#8220;onward&#8221; на &#8220;forward&#8221;  с учетом регистра</td>
</tr>
<tr>
<td>:%s/ *$//g</td>
<td>Убрать все пробелы</td>
</tr>
<tr>
<td>:g/string/d</td>
<td>Удалить все строки, содержащие &#8220;string&#8221;</td>
</tr>
<tr>
<td>:v/string/d</td>
<td>Удалить все строки, не содержащие &#8220;string&#8221;</td>
</tr>
<tr>
<td>:s/Bill/Steve/</td>
<td>Заменить первое вхождение &#8220;Bill&#8221; на &#8220;Steve&#8221; в текущей строке</td>
</tr>
<tr>
<td>:s/Bill/Steve/g</td>
<td>Заменить все вхождения &#8220;Bill&#8221; на &#8220;Steve&#8221; в текущей строке</td>
</tr>
<tr>
<td>:%s/\r//g</td>
<td>Убрать символ возврата каретки (Такие тексты обычно приходят от windows-пользователей)</td>
</tr>
<tr>
<td>:%s#&gt;[^&lt;]\+&gt;##g</td>
<td>Очистить текст от HTML-тегов</td>
</tr>
<tr>
<td>:%s/^\(.*\)\n\1$/\1/</td>
<td>Удалить строки, повторяющиеся дважды</td>
</tr>
<tr>
<td>Ctrl+a</td>
<td>Увеличить число под курсором на единицу</td>
</tr>
<tr>
<td>Ctrl+x</td>
<td>Уменьшить число под курсором на единицу</td>
</tr>
<tr>
<td>ggVGg?</td>
<td>Преобразовать текст в Rot13</td>
</tr>
</table>
<h2>Регистр</h2>
<table border="0" cellspacing="3">
<tr>
<td>Vu</td>
<td>Перевести строку в нижний регистр</td>
</tr>
<tr>
<td>VU</td>
<td>Перевести строку в верхний регистр</td>
</tr>
<tr>
<td>g~~</td>
<td>Инвертировать регистр</td>
</tr>
<tr>
<td>vEU</td>
<td>Перевести слово под курсором в верхний регистр</td>
</tr>
<tr>
<td>vE~</td>
<td>Инвертировать регистр слова</td>
</tr>
<tr>
<td>ggguG</td>
<td>Перевести весь текст в нижний регистр</td>
</tr>
<tr>
<td>:set ignorecase</td>
<td>Регистронезависимый поиск</td>
</tr>
<tr>
<td>:set smartcase</td>
<td>Игнорировать регистр при поиске, если в искомом выражении нет символов верхнего регистра</td>
</tr>
<tr>
<td>:%s/\&lt;./\u&#038;/g</td>
<td>Перевести первую букву каждого слова в верхний регистр</td>
</tr>
<tr>
<td>:%s/\&lt;./\l&#038;/g</td>
<td>Перевести первую букву каждого слова в нижний регистр</td>
</tr>
<tr>
<td>:%s/.*/\u&#038;</td>
<td>Перевести первую букву первого слова в каждой строке в верхний регистр</td>
</tr>
<tr>
<td>:%s/.*/\l&#038;</td>
<td>Перевести первую букву первого слова в каждой строке в нижний регистр</td>
</tr>
</table>
<h2>Чтение/запись файлов</h2>
<table border="0" cellspacing="3">
<tr>
<td>:1,10 w outfile</td>
<td>Записать в <em>outfile</em> с первой по десятую строки</td>
</tr>
<tr>
<td>:1,10 w >> outfile</td>
<td>Добавить в <em>outfile</em> с первой по десятую строки</td>
</tr>
<tr>
<td>:r infile</td>
<td>Вставить содержимое файла <em>infile</em></td>
</tr>
<tr>
<td>:23r infile</td>
<td>Вставить содержимое файла <em>infile</em> после 23 строки</td>
</tr>
</table>
<h2>Навигация по ФС</h2>
<table border="0" cellspacing="3">
<tr>
<td>:e .</td>
<td>Открыть встроенный файл-менеджер</td>
</tr>
<tr>
<td>:Sex</td>
<td>Разбить окно и открыть встроенный файл менеджер</td>
</tr>
<tr>
<td>:browse e</td>
<td>Графический файл-менеджер</td>
</tr>
<tr>
<td>:ls</td>
<td>Список буферов</td>
</tr>
<tr>
<td>:cd ..</td>
<td>Перейти в родительскую директорию</td>
</tr>
<tr>
<td>:args</td>
<td>Список открытых файлов</td>
</tr>
<tr>
<td>:args *.php</td>
<td>Открыть все файлы с расширением *.php</td>
</tr>
<tr>
<td>:grep expression *.php</td>
<td>Показать список файлов с расширением php, содержащих в имени <em>expression</em></td>
</tr>
<tr>
<td>gf</td>
<td>Открыть файл с именем, равным слову, находящемуся под курсором</td>
</tr>
</table>
<h2>Взаимодействие с ОС</h2>
<table border="0" cellspacing="3">
<tr>
<td>:!pwd</td>
<td>Выполнить команду <code>pwd</code> и вернуться</td>
</tr>
<tr>
<td>!!pwd</td>
<td>Выполнить команду <code>pwd</code> и вставить результат в редактор</td>
</tr>
<tr>
<td>:sh</td>
<td>Открыть шелл</td>
</tr>
<tr>
<td>$exit</td>
<td>Вернуться в редактор из шелла</td>
</tr>
</table>
<h2>Выравнивание</h2>
<table border="0" cellspacing="3">
<tr>
<td>:%!fmt</td>
<td>Выровнять все строки</td>
</tr>
<tr>
<td>!}fmt</td>
<td>Выровнять все строки в текущей позиции</td>
</tr>
<tr>
<td>5!!fmt</td>
<td>Выровнять следующие 5 строк</td>
</tr>
</table>
<h2>Вкладки</h2>
<table border="0" cellspacing="3">
<tr>
<td>:tabnew</td>
<td>Создать новую вкладку</td>
</tr>
<tr>
<td>gt</td>
<td>Перейти на следующую вкладку</td>
</tr>
<tr>
<td>:tabfirst</td>
<td>Перейти на первую вкладку</td>
</tr>
<tr>
<td>:tablast</td>
<td>Перейти на последнюю вкладку</td>
</tr>
<tr>
<td>:tabm n(position)</td>
<td>Изменить порядок вкладок</td>
</tr>
<tr>
<td>:tabdo %s/foo/bar/g</td>
<td>Выполнить команду во всех вкладках</td>
</tr>
<tr>
<td>:tab ball</td>
<td>Поместить все открытые файлы во вкладки</td>
</tr>
</table>
<h2>Разделение окна</h2>
<table border="0" cellspacing="3">
<tr>
<td>:e filename</td>
<td>Редактировать <em>filename</em> в текущем окне</td>
</tr>
<tr>
<td>:split filename</td>
<td>Разделить окно и открыть <em>filename</em></td>
</tr>
<tr>
<td>ctrl-w + стрелка ВВЕРХ</td>
<td>Переместить курсор в верхнее окно</td>
</tr>
<tr>
<td>ctrl-w ctrl-w</td>
<td>Переместить курсор в следующее окно</td>
</tr>
<tr>
<td>ctrl-w_</td>
<td>Максимизировать текущее окно</td>
</tr>
<tr>
<td>ctrl-w=</td>
<td>Подогнать окна по размеру</td>
</tr>
<tr>
<td>10 ctrl-w+</td>
<td>Увеличить текущее окно на 10 строк</td>
</tr>
<tr>
<td>:vsplit file</td>
<td>Вертикально разделить окно</td>
</tr>
<tr>
<td>:sview file</td>
<td>Разделить окно и открыть <em>file</em> только для чтения</td>
</tr>
<tr>
<td>:hide</td>
<td>Закрыть текущее окно</td>
</tr>
<tr>
<td>:only</td>
<td>Закрыть все окна, кроме текущего</td>
</tr>
<tr>
<td>:b 2</td>
<td>Открыть #2  в текущем окне</td>
</tr>
</table>
<h2>Автодополнение</h2>
<table border="0" cellspacing="3">
<tr>
<td>Ctrl+n Ctrl+p (в режиме вставки)</td>
<td>Дополнить слово</td>
</tr>
<tr>
<td>Ctrl+x Ctrl+l</td>
<td>Дополнить строку</td>
</tr>
<tr>
<td>:set dictionary=dict</td>
<td>Установить словарь</td>
</tr>
<tr>
<td>Ctrl+x Ctrl+k</td>
<td>Дополнение из словаря</td>
</tr>
</table>
<h2>Метки</h2>
<table border="0" cellspacing="3">
<tr>
<td>mk</td>
<td>Пометить текущую позиция как k</td>
</tr>
<tr>
<td>‘k</td>
<td>Перейти к метке k</td>
</tr>
<tr>
<td>d’k</td>
<td>Удалить все до метки k</td>
</tr>
</table>
<h2>Сокращения</h2>
<table border="0" cellspacing="3">
<tr>
<td>:ab mail mail@provider.org</td>
<td>Определить <em>mail</em> как сокращение от <em>mail@provider.org</em></td>
</tr>
</table>
<h2>Отступы</h2>
<table border="0" cellspacing="3">
<tr>
<td>:set autoindent</td>
<td>Включить автоматическую расстановку отступов</td>
</tr>
<tr>
<td>:set smartindent</td>
<td>Включить &#8220;умную&#8221; расстановку отступов</td>
</tr>
<tr>
<td>:set shiftwidth=4</td>
<td>Установить отступ равный 4 пробелам</td>
</tr>
<tr>
<td>ctrl-t, ctrl-d</td>
<td>Убрать/добавить отступ в режиме вставки</td>
</tr>
<tr>
<td>&lt;&lt;</td>
<td>Добавить отступ</td>
</tr>
<tr>
<td>&gt;&gt;</td>
<td>Убрать отступ</td>
</tr>
</table>
<h2>Подсветка синтаксиса</h2>
<table border="0" cellspacing="3">
<tr>
<td>:syntax on</td>
<td>Включить подсветку</td>
</tr>
<tr>
<td>:syntax off</td>
<td>Выключить подсветку</td>
</tr>
<tr>
<td>:set syntax=perl</td>
<td>Установить режим подсветки</td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://boombick.org/blog/posts/84/feed</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Установка nginx, php5 CGI и MySQL</title>
		<link>http://boombick.org/blog/posts/79</link>
		<comments>http://boombick.org/blog/posts/79#comments</comments>
		<pubDate>Tue, 18 Aug 2009 13:40:19 +0000</pubDate>
		<dc:creator>boombick</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[Debian]]></category>
		<category><![CDATA[Network]]></category>
		<category><![CDATA[web-servers]]></category>
		<category><![CDATA[Для начинающих]]></category>

		<guid isPermaLink="false">http://boombick.org/blog/posts/79</guid>
		<description><![CDATA[Nginx (произносится как &#8220;энджин икс&#8221;) &#8211; это легкий высокопроизводительный веб-сервер с открытым исходным кодом. Он известен своей стабильностью, большим набором функций, сравнительной простотой конфигурации, а также весьма низкой требовательностью к ресурсам. В этой статье я опишу процесс установки nginx, PHP5 в CGI-режиме и MySQL на Debian Lenny. В нашем примере установка будет производится на сервер [...]]]></description>
			<content:encoded><![CDATA[<p>Nginx (произносится как &#8220;энджин икс&#8221;) &#8211; это легкий высокопроизводительный веб-сервер с открытым исходным кодом. Он известен своей стабильностью, большим набором функций, сравнительной простотой конфигурации, а также весьма низкой требовательностью к ресурсам. В этой статье я опишу процесс установки nginx, PHP5 в CGI-режиме и MySQL на Debian Lenny.<br />
<span id="more-79"></span><br />
В нашем примере установка будет производится на сервер с доменным именем <code>server1.example.com</code> и IP-адресом <code>192.168.1.100</code></p>
<p><strong>Установка MySQL 5.0</strong></p>
<blockquote><p>aptitude install mysql-server mysql-client</p></blockquote>
<p>В процессе установки вас попросят ввести пароль для пользователя root. Этот пользователь не имеет ничего общего с системным пользователем root. Этот пароль будет использован для пользователя, обладающего суперпривелегиями для самой MySQL:</p>
<blockquote>
<pre>
New password for the MySQL "root" user: &lt;-- yourrootsqlpassword
Repeat password for the MySQL "root" user: &lt;-- yourrootsqlpassword</pre>
</blockquote>
<p><strong>Установка Nginx</strong><br />
Nginx есть в репозитории Debian, что существенно упрощает нашу задачу :)<br />
Установим и запустим его:</p>
<blockquote><p>aptitude install nginx<br />
/etc/init.d/nginx start</p></blockquote>
<p>Наберите в браузере IP-адрес или хостнейм сервера (например <code>http://192.168.0.100</code>) и вы увидите стартовую страницу nginx<br />
<a href="http://boombick.org/blog/wp-content/uploads/2009/08/1.png" title="1.png"><img src="http://boombick.org/blog/wp-content/uploads/2009/08/1.thumbnail.png" alt="1.png" /></a></p>
<p><strong>Установка PHP5</strong><br />
Для &#8220;общения&#8221; между nginx и PHP мы будем использовать FastCGI. К счастью, в репозиториях Debian есть пакет, обеспечиващий поддержку FCGI в PHP. Установим PHP</p>
<blockquote><p>aptitude install php5-cgi php5-mysql php5-curl php5-gd php5-idn php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-mhash php5-ming php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl</p></blockquote>
<p>Отредактируйте файл <code>/etc/php5/cgi/php.ini</code> добавив в его конец следующую строку:</p>
<blockquote>
<pre>
cgi.fix_pathinfo = 1</pre>
</blockquote>
<p>В Debian нет самостоятельного приложения для FastCGI, поэтому мы воспользуемся <code>spawn-fcgi</code>, которая входит в состав lighttpd:</p>
<blockquote><p>aptitude install lighttpd</p></blockquote>
<p>И после установки получим сразу же получим ошибку:</p>
<blockquote>
<pre>Starting web server: lighttpd2009-03-19 15:58:09: (network.c.300) can't bind to port: 80 Address already in use
 failed!</pre>
</blockquote>
<p>Логично, 80-й порт у нас занят nginx-ом. Поэтому сделаем так, чтобы Лайти не запускался при загрузке системы:</p>
<blockquote><p>update-rc.d -f lighttpd remove</p></blockquote>
<p>Мы установили Лайти только для того, чтобы воспользовать крайне полезной для наших целей программой, идущей с ним в комплекте: <code>/usr/bin/spawn-fcgi</code>, именно ее мы будем использовать для запуска процессов FastCGI. Для краткого ознакомления с ее возможностями выполните команду</p>
<blockquote><p>spawn-fcgi &#8211;help</p></blockquote>
<p>Для запуска PHP FastCGI-демона на 9000 порту на сервере <code>localhost</code> от пользователя <code>www-data</code> выполните</p>
<blockquote>
<pre>
/usr/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www-data -g www-data -f /usr/bin/php5-cgi -P /var/run/fastcgi-php.pid
</pre>
</blockquote>
<p>И чтобы каждый раз не приходилось вводить это вручную, команду можно прописать в <code>/etc/rc.local</code></p>
<p><strong>Настройка Nginx</strong><br />
Конфигурационный файл nginx расположен здесь: <code>/etc/nginx/nginx.conf</code>. Для начала (необязательно) увеличим количество рабочих процессов и поменяем параметр <code>keepalive_timeout</code>:</p>
<blockquote>
<pre>[...]
worker_processes  5;
[...]
    keepalive_timeout   2;
[...]</pre>
</blockquote>
<p>Настройки виртуальных хостов расположены в секции <code>server {}</code>, хост по умолчанию описан в <code>/etc/nginx/sites-available/default</code>, модифицируйте его следующим образом:</p>
<blockquote>
<pre>
[...]
server {
        listen   80;
        server_name  _;

        access_log  /var/log/nginx/localhost.access.log;

        location / {
                root   /var/www/nginx-default;
                index  index.php index.html index.htm;
        }

        location /doc {
                root   /usr/share;
                autoindex on;
                allow 127.0.0.1;
                deny all;
        }

        location /images {
                root   /usr/share;
                autoindex on;
        }

        #error_page  404  /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
                root   /var/www/nginx-default;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
                #proxy_pass   http://127.0.0.1;
        #}

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        location ~ \.php$ {
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  /var/www/nginx-default$fastcgi_script_name;
                include        fastcgi_params;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        location ~ /\.ht {
                deny  all;
        }
}
[...]</pre>
</blockquote>
<p><code>server_name _;</code> &#8211; имя хоста &#8220;по умолчанию&#8221; (конечно же, никто не мешает явно указать имя хоста, например <code>example.com</code>)<br />
В выражении <code>location /</code> мы указываем индексный файл (<code>index.php</code>) и document root (<code>/var/www/nginx-default</code>)<br />
Важная часть для PHP &#8211; это <code>location ~ \.php$ {}</code>, раскомментируйте ее. Не забудьте проверить, что вы изменили строку <code>fastcgi_param</code> на <code>fastcgi_param SCRIPT_FILENAME /var/www/nginx-default$fastcgi_script_name</code> (замените <code>/var/www/nginx-default</code> на ваш реальный путь к document root), иначе интерпретатор PHP может не найти запрашиваемый вами через браузер скрипт.<br />
Удостоверьтесь, что между <code>include</code> и <code>fastcgi_params</code> есть пробел, в оригинальном файле они записаны как одно слово &#8211; это ошибка.<br />
Перезапустите <code>nginx</code></p>
<blockquote><p>/etc/init.d/nginx restart</p></blockquote>
<p>Создайте тестовый файл PHP со следующим содержанием</p>
<blockquote>
<pre>
&lt;?php
phpinfo();
?&gt;</pre>
</blockquote>
<p>Сохраните в вашей document root и откройте его в браузере (<code>http://192.168.0.100/info.php</code>)<br />
<a href="http://boombick.org/blog/wp-content/uploads/2009/08/2.png" title="2.png"><img src="http://boombick.org/blog/wp-content/uploads/2009/08/2.thumbnail.png" alt="2.png" /></a><br />
Обратите внимание на строку ServerAPI</p>
]]></content:encoded>
			<wfw:commentRss>http://boombick.org/blog/posts/79/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	<img style='margin:0;padding:0;border:0;' width='1px' height='1px' src="http://boombick.org/blog/wp-content/plugins/mystat/mystat.php?act=time_load&id=0&rnd=104343440" /></channel>
</rss>

