<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2enclosuresfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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:media="http://search.yahoo.com/mrss/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Український IT-блог</title>
	
	<link>http://itblog.org.ua</link>
	<description>Експериментальний веблог</description>
	<pubDate>Thu, 25 Jun 2009 18:57:43 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Itblog-ua" type="application/rss+xml" /><feedburner:emailServiceId>Itblog-ua</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Тонке налаштування Buildbot’а</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/o_msBo0NZTI/194</link>
		<comments>http://itblog.org.ua/post/194#comments</comments>
		<pubDate>Thu, 25 Jun 2009 18:55:22 +0000</pubDate>
		<dc:creator>Jolly Roger</dc:creator>
		
		<category><![CDATA[Howto]]></category>

		<category><![CDATA[Софт]]></category>

		<category><![CDATA[Buildbot]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[автоматизація]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/?p=194</guid>
		<description><![CDATA[Сьогодні ми продовжимо налаштування Buildbot&#8217;а. Сподіваюсь, читач вже знайомий з попереднім матеріалом на дану тему, тому тут будуть вказані типові запитання, вдосконалення, можливі проблеми без зайвих слів.

Додання нового клієнта
Насправді, додати нового клієнта не так вже й складно. Для цього необхідно

Додати логін і пароль бота до параметру buildslaves
Прив&#8217;язати до процесу збирання
Внести в розклад збирання

Слід не забути [...]]]></description>
			<content:encoded><![CDATA[<p>Сьогодні ми продовжимо налаштування Buildbot&#8217;а. Сподіваюсь, читач вже знайомий з попереднім матеріалом на дану тему, тому тут будуть вказані типові запитання, вдосконалення, можливі проблеми без зайвих слів.</p>
<p><span id="more-194"></span></p>
<h3>Додання нового клієнта</h3>
<p>Насправді, додати нового клієнта не так вже й складно. Для цього необхідно</p>
<ol>
<li>Додати логін і пароль бота до параметру <em>buildslaves</em></li>
<li>Прив&#8217;язати до процесу збирання</li>
<li>Внести в розклад збирання</li>
</ol>
<p>Слід не забути одну просту річ: якщо доступ до репозитарію віддалений, необхідно хоча б раз виконати вхід до<br />
віддаленої системи вручну. Якщо цього не зробити, бот не зможе отримати джерельні коди проекту, оскільки буде наштовхуватись на дві помилки: </p>
<ol>
<li>невідомий сертифікат (вирішується одноразовим входом з доданням сертифікату в довірені)</li>
<li>незареєстрований користувач (вирішується одноразовим входом з введенням та автоматичним збереженням реєстраційних даних клієнтом subversion).</li>
</ol>
<h3>Фільтрація по розширенню файлів</h3>
<p>Можливі такі випадки, коли в репозитарії зберігаються не лише джерельні коди, а ще й супутня документація, файли опису, які не впливають на процес збирання. При цьому бот з базовим налаштуванням при оновленні подібних файлів буде все одно робити збірку. Щоб уникнути цього необхідно для початку створити об&#8217;єкт типу Callable (в простих варіантах функція підійде якнайкраще), який буде повертати істину у випадку, якщо збирання проекту необхідне. Так, для Java проекту, описаного в попередній статті, я використав:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> checkIfBuildNeeded<span style="color: black;">&#40;</span>change<span style="color: black;">&#41;</span>:
	regexp = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\.</span>java$|<span style="color: #000099; font-weight: bold;">\.</span>idl$|<span style="color: #000099; font-weight: bold;">\.</span>jar$|build<span style="color: #000099; font-weight: bold;">\.</span>xml$'</span>,<span style="color: #dc143c;">re</span>.<span style="color: black;">IGNORECASE</span><span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> change.<span style="color: black;">files</span>: 
		<span style="color: #ff7700;font-weight:bold;">if</span> regexp.<span style="color: black;">search</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>: 
			<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span> 
	<span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span></pre></td></tr></table></div>

<p>Тепер слід вказати дану функцію як перевірку в налаштуваннях об&#8217;єкта Sheduler:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>11
12
13
14
15
16
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">scheduler</span> <span style="color: #ff7700;font-weight:bold;">import</span> Scheduler
&nbsp;
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'schedulers'</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'schedulers'</span><span style="color: black;">&#93;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Scheduler<span style="color: black;">&#40;</span>name=<span style="color: #483d8b;">&quot;basic&quot;</span>,
	fileIsImportant=checkIfBuildNeeded, 
	builderNames=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;quick&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h3>Пересилання готових збірок</h3>
<p>Уявімо, що бот в результаті процесу збирання генерує ще й готові до встановлення бінарні пакети, як, наприклад, .deb, .rpm, чи готує зрізи джерельних кодів, при цьому було б бажаним переслати файли з buildbot-клієнта на buildbot-сервер, де вони б знаходилися в загальнодоступній директорії. Можлива й зворотня ситуація: для перевірки деякого функціоналу необхідні сценарії, згенеровані іншим проектом. Для таких задач можна використати спеціальні кроки збирання FileUpload та FileDownload, що знаходяться в buildbot.steps.transfer. Ось невеличкий приклад використання одного з цих кроків:</p>

<div class="wp_syntax"><div class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">steps</span>.<span style="color: black;">shell</span> <span style="color: #ff7700;font-weight:bold;">import</span> ShellCommand
<span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">steps</span>.<span style="color: black;">transfer</span> <span style="color: #ff7700;font-weight:bold;">import</span> FileUpload
&nbsp;
f.<span style="color: black;">addStep</span><span style="color: black;">&#40;</span>ShellCommand<span style="color: black;">&#40;</span>name=<span style="color: #483d8b;">&quot;Package&quot;</span>, command=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;tar&quot;</span>, <span style="color: #483d8b;">&quot;zxvf&quot;</span>, <span style="color: #483d8b;">&quot;build.tar.gz&quot;</span>, <span style="color: #483d8b;">&quot;build&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
f.<span style="color: black;">addStep</span><span style="color: black;">&#40;</span>FileUpload<span style="color: black;">&#40;</span>slavesrc=<span style="color: #483d8b;">&quot;build.tar.gz&quot;</span>,
    masterdest=<span style="color: #483d8b;">&quot;~/public_html/build&quot;</span>+<span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strftime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%Y%m%d-%H%M%S&quot;</span><span style="color: black;">&#41;</span>+<span style="color: #483d8b;">&quot;tar.gz&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Окрім того, що пакет буде надісланий на сервер, він ще й матиме унікальну назву,що вказуватиме на час його створення. Це можливо завдяки тому, що кожен об&#8217;єкт-крок виконується інтерпретатором в момент надсилання його клієнту, в даному випадку генеруючи їм&#8217;я файлу на сервері. </p>
<h3>Залежні збірки</h3>
<p>Уявімо, що зібраний на відповідному клієнті пакет повинен бути встановлений на окремій тестовій машині, де буде детально протестований автоматичними засобами. В такому випадку зручно використовувати залежні збірки. Вони дозволять не виконувати тестів у випадку неуспішного збирання пакету. Щоб скористатись даною можливістю, слід в кроки збирання додати об&#8217;єкт Trigger, який буде викликати відповідний процес збирання через об&#8217;єкт Sheduler.</p>

<div class="wp_syntax"><div class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">steps</span>.<span style="color: black;">trigger</span> <span style="color: #ff7700;font-weight:bold;">import</span> Trigger
     f.<span style="color: black;">addStep</span><span style="color: black;">&#40;</span>Trigger<span style="color: black;">&#40;</span>schedulerNames=<span style="color: black;">&#91;</span><span style="color: #483d8b;">'package'</span><span style="color: black;">&#93;</span>,
                       waitForFinish=<span style="color: #008000;">True</span>,
                       updateSourceStamp=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Завдяки кроку Trigger також можна запускати процеси одночасно на кількох машинах.</p>
<h3>Корисні посилання</h3>
<p>Наостанок, якщо вам до вподоби автоматизація процесів вашої роботи, і ви бачите зручність у використанні Buildbot-а в якості системи неперервної інтеграції, автоматизації та інших подібних операцій,  під рукою повинна бути література, в якій можна було б отримати необхідні знання. Сподіваюсь, ці посилання зекономлять вам купу часу:</p>
<p>Веб-сайт проекту: <a href="http://buildbot.net">http://buildbot.net</a><br />
Документація користувача: <a href="file:///usr/share/doc/buildbot/buildbot.html">/usr/share/buildbot/buildbot.html</a> в кожному Linux дистрибутиві зі встановленим Buildbot&#8217;ом.<br />
Документація розробника: <a href="http://buildbot.sourceforge.net/API-0.7.5/">http://buildbot.sourceforge.net/API-0.7.5/</a></p>
<p>На цьому я завершую цикл статей про чудовий інструмент в автоматизації та неперервній інтеграції &#8212; Buildbot. Попереду ще багато інструментів, які не менш важливі для втілення ваших мрій у рядках коду. Не перемикайтесь!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=o_msBo0NZTI:W8x6bc8Uy3A:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=o_msBo0NZTI:W8x6bc8Uy3A:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=o_msBo0NZTI:W8x6bc8Uy3A:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/o_msBo0NZTI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/194/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/194</feedburner:origLink></item>
		<item>
		<title>Автоматизація процесу розробки: працюємо з Buildbot’ом</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/_IhXoV7p1vA/175</link>
		<comments>http://itblog.org.ua/post/175#comments</comments>
		<pubDate>Fri, 12 Jun 2009 13:59:47 +0000</pubDate>
		<dc:creator>Jolly Roger</dc:creator>
		
		<category><![CDATA[Howto]]></category>

		<category><![CDATA[Софт]]></category>

		<category><![CDATA[Buildbot]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[twisted]]></category>

		<category><![CDATA[автоматизація]]></category>

		<category><![CDATA[управління проектами]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/?p=175</guid>
		<description><![CDATA[Як я й обіцяв в минулій статті, сьогодні ми дослідимо реальний приклад використання системи неперервної інтеграції під назвою BuildBot. Ні сам процес розробки, ні структура проекту не вважаються ідеальними, однак саме завдяки їм у мене зараз є можливість написати як можливо вижити в, здавалося б, такому хаотичному проекті.
Постановка задачі
Проект на Java(використовується система збирання Ant) в [...]]]></description>
			<content:encoded><![CDATA[<p>Як я й обіцяв в минулій статті, сьогодні ми дослідимо реальний приклад використання системи неперервної інтеграції під назвою BuildBot. Ні сам процес розробки, ні структура проекту не вважаються ідеальними, однак саме завдяки їм у мене зараз є можливість написати як можливо вижити в, здавалося б, такому хаотичному проекті.</p>
<h3>Постановка задачі</h3>
<p>Проект на Java(використовується система збирання Ant) в репозитарії Subversion знаходиться за адресою https://project.example.com/svn . Необхідно проводити аудит працездатності системи щоразу після внесення змін до нього. Результати збирання системи надсилаються автору змін у випадку успішного результату, або ж у список розсилки всього проекту, якщо процес пройшов невдало. </p>
<p>Вибір між CruiseControl, про який мені розповіли співробітники, та BuildBot, з яким я встиг познайомитись в якості розробника, був досить складний. Проект був вже тоді немаленький(на даний момент весь репозитарій складає 6Гб місця), після тестування його переносила на продуктивні сервери окрема людина. Enterprise, одним словом. І я, довірившись особистому знайомству, вибрав BuildBot. І не прогадав.</p>
<p><span id="more-175"></span></p>
<h3>Встановлення</h3>
<p>Оскільки BuildBot має клієнт-серверну архітектуру, його можна запустити в двох режимах:</p>
<ul>
<li> <strong>Master:</strong> визначає, що, коли, і як робити, реалізує всі системи сповіщення </li>
<li> <strong>Slave:</strong> старанно виконує всі вказівки Master-а</li>
</ul>
<p>Для спрощення комунікації, сервер був встановлений на машині, яка тримала репозитарій. Нехай шлях до репозитарію на сервері &#8212; /var/repos/project. DNS-ім&#8217;я сервера &#8212; example.com. Встановлення BuildBot&#8217;а в Debian проходить без жодних проблем:</p>
<pre># aptitude install buildbot </pre>
<p>Після чого BuildBot буде встановлений з усіма необхідними залежностями. Тепер слід створити сервер, який нестиме основне інформаційне навантаження та клієнт, який буде виконувати процес збирання. Для чистоти експерименту, обидва будуть працювати під власними користувачами:</p>
<pre>
# addgroup buildbot
# adduser --group buildbot buildmaster
# adduser --group buildbot buildslave
</pre>
<p>Тепер власне створення сервера:</p>
<pre>
# su - buildmaster
$ mkdir project
$ buildbot create-master project
</pre>
<h3>Налаштування сервера</h3>
<p>Після цього в директорії myproject створиться базовий набір файлів, а також деякі допоміжні сценарії для запуску сервера. Сам же конфігураційний файл зветься <em>master.cfg</em>. Хоча можна поправити та перейменувати вже створений master.cfg.sample, я залишу його для тренувань, натомість створимо власну конфігурацію:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- python -*-</span>
<span style="color: #808080; font-style: italic;"># ex: set syntax=python:</span>
&nbsp;
c = BuildmasterConfig = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># PROJECT IDENTITY</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'projectName'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">&quot;Test project&quot;</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'projectURL'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">&quot;http://project.example.com/&quot;</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'buildbotURL'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">&quot;http://buildbot.example.com/&quot;</span></pre></td></tr></table></div>

<p>Тепер визначимо, скільки клієнтів в нас є, і скільки збірок вони можуть виконувати одночасно. Для сервера, на який покладено багато задач, не раджу ставити більше одного. Тим більше, що всі дії кладуться в чергу, а тому нічого не буде упущене.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># BUILDSLAVES</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">buildslave</span> <span style="color: #ff7700;font-weight:bold;">import</span> BuildSlave
&nbsp;
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'slaves'</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'slaves'</span><span style="color: black;">&#93;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>BuildSlave<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;local-bot&quot;</span>, <span style="color: #483d8b;">&quot;local-password&quot;</span>,max_builds=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'slavePortnum'</span><span style="color: black;">&#93;</span> = <span style="color: #ff4500;">9989</span></pre></td></tr></table></div>

<p>Коли загальні відомості щодо проекту ми вказали, розберемося з тим, як бот дізнається про те, що в репозитарії було щось змінено. Сервер очікує встановлення зв&#8217;язку на вказаний нами порт. До цього порту можуть підключатись як клієнти, що виконують власне збирання системи(в даному варіанті маємо одного бота, який працює локально), так і спеціальні програми, що вказують на зміни в проекті. Для реалізації даної моделі додамо наступні рядки в налаштування:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>17
18
19
20
21
22
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># CHANGESOURCES</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">changes</span>.<span style="color: black;">pb</span> <span style="color: #ff7700;font-weight:bold;">import</span> PBChangeSource
&nbsp;
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'change_source'</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'change_source'</span><span style="color: black;">&#93;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span> PBChangeSource<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Не завжди існує можливість отримати повідомлення про оновлення репозитарію. В таких випадках замість того, щоб очікувати підключення за вказаним портом можна власноруч періодично опитувати SVN репозитарій на наявність оновлень. Це можна зробити за допомогою об&#8217;єкту SVNPoller. Якщо ж ви отримуєте інформацію про оновлення репозитарію поштою, то Bildbot можна натравити на поштову скриньку (можливе використання як формату mbox, так і mdir), і таким чином сповіщувати систему.</p>
<p>Нарешті, визначаємо те, як буде проходити сам процес збирання проекту. Для цього запишемо:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;">localsvnroot  = <span style="color: #483d8b;">'file:///var/repos/project/'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># BUILDERS</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">process</span> <span style="color: #ff7700;font-weight:bold;">import</span> factory
<span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">steps</span>.<span style="color: black;">source</span> <span style="color: #ff7700;font-weight:bold;">import</span> SVN
<span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">steps</span>.<span style="color: black;">shell</span> <span style="color: #ff7700;font-weight:bold;">import</span> Compile
&nbsp;
localFastSourceUpdate = SVN<span style="color: black;">&#40;</span>svnurl=localsvnroot,mode=<span style="color: #483d8b;">&quot;update&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
antCleanup = Compile<span style="color: black;">&#40;</span>command=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;ant&quot;</span>,<span style="color: #483d8b;">&quot;cleanup&quot;</span><span style="color: black;">&#93;</span>, name=<span style="color: #483d8b;">&quot;Cleanup&quot;</span><span style="color: black;">&#41;</span>
antCompile = Compile<span style="color: black;">&#40;</span>command=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;ant&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
quickBuildFactory = factory.<span style="color: black;">BuildFactory</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>localFastSourceUpdate, antCleanup, antCompile<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
quickBuild = <span style="color: black;">&#123;</span>
	<span style="color: #483d8b;">'name'</span>: <span style="color: #483d8b;">&quot;quick&quot;</span>,
	<span style="color: #483d8b;">'slavename'</span>: <span style="color: #483d8b;">&quot;local-bot&quot;</span>,
	<span style="color: #483d8b;">'builddir'</span>: <span style="color: #483d8b;">&quot;quick&quot;</span>,
	<span style="color: #483d8b;">'factory'</span>: quickBuildFactory <span style="color: black;">&#125;</span>
&nbsp;
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'builders'</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#91;</span>quickBuild<span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Вище вказаний код вимагає деяких пояснень. Очевидно, процес збирання програми руками, виглядає як</p>
<pre>
$ svn up
$ ant cleanup
$ ant
</pre>
<p>Рядки 40-50 визначають кроки, які необхідно виконати для збирання програми. Далі ці кроки збираються в єдиний об&#8217;єкт, який надалі буде управляти процесом збирання. В останніх рядках виконується прив&#8217;язка до конкретного імені та списку клієнтів, на яких необхідно проводити збирання. Останнім рядком додаємо наш об&#8217;єкт до налаштувань.</p>
<p>Наступним кроком буде прив&#8217;язка процесу збирання проекту до події оновлення репозитарію. Для цього використовується об&#8217;єкт Sheduler. Його різновидів достатньо для більшості задач: збирати за повідомленням ззовні, періодичне виконання, виконання за розкладом тощо.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>45
46
47
48
49
50
51
52
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># SCHEDULERS</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">scheduler</span> <span style="color: #ff7700;font-weight:bold;">import</span> Scheduler
&nbsp;
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'schedulers'</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'schedulers'</span><span style="color: black;">&#93;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>Scheduler<span style="color: black;">&#40;</span>name=<span style="color: #483d8b;">&quot;dirty and quick&quot;</span>,
	treeStableTimer=<span style="color: #ff4500;">10</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">60</span>,
	builderNames=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;quick&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Параметр treeStableTimer визначає час в секундах(в даному випадку 10 хвилин), протягом якого в репозитарій не повинні бути внесені зміни для початку процесу збирання. У разі швидко виявленої помилки та своєчасних внесень змін до репозитарію, процес збирання буде виконаний лиш один раз. Це дозволить розробнику не привертати до себе зайвої уваги проблемами з процесом збирання проекту.</p>
<p>Наостанок, визначимо служби сповіщення. Для поставленої задачі достатньо налаштувати пошту, однак web-інтерфейс ніколи зайвим не був.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># STATUS TARGETS</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">status</span> <span style="color: #ff7700;font-weight:bold;">import</span> html
<span style="color: #ff7700;font-weight:bold;">from</span> buildbot.<span style="color: black;">status</span> <span style="color: #ff7700;font-weight:bold;">import</span> html, mail
&nbsp;
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'status'</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'status'</span><span style="color: black;">&#93;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>html.<span style="color: black;">WebStatus</span><span style="color: black;">&#40;</span>http_port=<span style="color: #ff4500;">80</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Send notification on build to committer</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'status'</span><span style="color: black;">&#93;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>mail.<span style="color: black;">MailNotifier</span><span style="color: black;">&#40;</span>fromaddr=<span style="color: #483d8b;">&quot;buildbot@example.com&quot;</span>,
	relayhost=<span style="color: #483d8b;">&quot;localhost&quot;</span>,
	lookup=<span style="color: #483d8b;">&quot;example.com&quot;</span>,
	mode=<span style="color: #483d8b;">&quot;all&quot;</span>,
	addLogs=<span style="color: #008000;">True</span>,
	builders=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;quick&quot;</span><span style="color: black;">&#93;</span>,
	sendToInterestedUsers=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Send notification to the mailing list if fails</span>
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'status'</span><span style="color: black;">&#93;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>mail.<span style="color: black;">MailNotifier</span><span style="color: black;">&#40;</span>fromaddr=<span style="color: #483d8b;">&quot;buildbot@example.com&quot;</span>,
	relayhost=<span style="color: #483d8b;">&quot;localhost&quot;</span>,
	mode=<span style="color: #483d8b;">&quot;failing&quot;</span>,
	builders=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;quick&quot;</span><span style="color: black;">&#93;</span>,
	extraRecipients=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;robots@example.com&quot;</span><span style="color: black;">&#93;</span>,
	sendToInterestedUsers=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ну ось, налаштування для сервера готові. Кілька ремарок щодо web-інтерфейсу. Хоча ми і вказували URL бота і головну сторінку проекту в перших рядках налаштувань, сервер очікує, що 80й порт не зайнятий на жодному інтерфейсі, інакше процес запуску не відбудеться.  В наступній статті я розповім, як здружити бота і Web-сервер на прикладі Apache2. Ну і не забудьте налаштувати MTA, щоб бот міг висилати пошту, або ж вкажіть інший SMTP сервер.</p>
<h3>Налаштування клієнта</h3>
<p>Встановлення клієнта для бота не вимагає надмірних зусиль. Для цього в більшості випадків достатньо виконати наступні команди:</p>
<pre>
# su - buildslave
$ mkdir project
$ buildbot create-slave project localhost:9989 local-bot local-password
</pre>
<h3>Налаштування репозитарію</h3>
<p>Оскільки ми очікуємо, що репозитарій має нас сповістити про оновлення, необхідно вказати наступні рядки у файлі<br />
/var/repos/project/hooks/post-commit:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #007800;">REPOS</span>=<span style="color: #ff0000;">&quot;$1&quot;</span>
<span style="color: #007800;">REV</span>=<span style="color: #ff0000;">&quot;$2&quot;</span>
<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>share<span style="color: #000000; font-weight: bold;">/</span>buildbot<span style="color: #000000; font-weight: bold;">/</span>contrib<span style="color: #000000; font-weight: bold;">/</span>svn_buildbot.py <span style="color: #660033;">--repository</span> <span style="color: #ff0000;">&quot;$REPOS&quot;</span> <span style="color: #660033;">--revision</span> <span style="color: #ff0000;">&quot;$REV&quot;</span> <span style="color: #660033;">--bbserver</span> localhost <span style="color: #660033;">--bbport</span> <span style="color: #000000;">9989</span></pre></td></tr></table></div>

<h3>Відлагодження та автозапуск</h3>
<p>Останнім штрихом буде запуск сервера і клієнта в інтерактивному режимі. Для цього правимо файл /etc/default/buildbot :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># buildbots to manage</span>
<span style="color: #666666; font-style: italic;"># add a new set of variables for each buildbot to start</span>
&nbsp;
BB_NUMBER<span style="color: #7a0874; font-weight: bold;">&#91;</span>0<span style="color: #7a0874; font-weight: bold;">&#93;</span>=0
BB_NAME<span style="color: #7a0874; font-weight: bold;">&#91;</span>0<span style="color: #7a0874; font-weight: bold;">&#93;</span>=<span style="color: #ff0000;">&quot;master&quot;</span>
BB_USER<span style="color: #7a0874; font-weight: bold;">&#91;</span>0<span style="color: #7a0874; font-weight: bold;">&#93;</span>=<span style="color: #ff0000;">&quot;buildmaster&quot;</span>
BB_BASEDIR<span style="color: #7a0874; font-weight: bold;">&#91;</span>0<span style="color: #7a0874; font-weight: bold;">&#93;</span>=<span style="color: #ff0000;">&quot;/home/buildmaster/project&quot;</span>
&nbsp;
BB_NUMBER<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>=<span style="color: #000000;">1</span>
BB_NAME<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>=<span style="color: #ff0000;">&quot;slave&quot;</span>
BB_USER<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>=<span style="color: #ff0000;">&quot;buildslave&quot;</span>
BB_BASEDIR<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>=<span style="color: #ff0000;">&quot;/home/buildslave/project&quot;</span></pre></td></tr></table></div>

<p>Тепер все це щастя можна сміливо запускати:</p>
<pre>
# /etc/init.d/buildbot start
</pre>
<p>Для відлагодження бота в процесі роботи необхідно додати в налаштування сервера наступні рядки:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>78
79
80
</pre></td><td class="code"><pre class="python python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># DEBUG CREDENTIALS</span>
&nbsp;
c<span style="color: black;">&#91;</span><span style="color: #483d8b;">'debugPassword'</span><span style="color: black;">&#93;</span>=<span style="color: #483d8b;">&quot;debugPassword&quot;</span></pre></td></tr></table></div>

<p>А для початку відлагодження слід виконати</p>
<pre>
$ buildbot debugclient buildbot.example.com:9989 debugPassword
</pre>
<p>після чого за допомогою графічного інтерфейсу можна викликати більшість операцій бота.</p>
<h3>Заключне слово</h3>
<p>Ну ось, система працює, однак вона ще далека від ідеалу: часто необхідно збирати один і той же продукт на різних платформах, централізовано викладувати т.з. нічні (Nightly) збірки, до того ж, поточна конфігурація не враховує можливих змін в структурі репозитарію, надлишковості збирань. Але це тема наступної статті.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=_IhXoV7p1vA:BBU7IOvooK8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=_IhXoV7p1vA:BBU7IOvooK8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=_IhXoV7p1vA:BBU7IOvooK8:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/_IhXoV7p1vA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/175/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/175</feedburner:origLink></item>
		<item>
		<title>Автоматизація процесу розробки: системи неперервної інтеграції</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/U7yqOsX7U2U/165</link>
		<comments>http://itblog.org.ua/post/165#comments</comments>
		<pubDate>Thu, 11 Jun 2009 10:55:17 +0000</pubDate>
		<dc:creator>Jolly Roger</dc:creator>
		
		<category><![CDATA[Софт]]></category>

		<category><![CDATA[Buildbot]]></category>

		<category><![CDATA[CruiseControl]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[twisted]]></category>

		<category><![CDATA[автоматизація]]></category>

		<category><![CDATA[управління проектами]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/?p=165</guid>
		<description><![CDATA[Сьогодні, шановний читачу, ми продовжимо розмову про те, як можна автоматизувати процес розробки програмного забезпечення, зменшити витрати часу на допоміжні роботи в великому колективі і сконцентруватись на власне розробці.
У колективі, кожен член якого працює над окремою незалежною частиною, стадія інтеграції є заключною. Саме в ній виявляються проблеми сумісності всіх компонентів системи, через це кінцева дата [...]]]></description>
			<content:encoded><![CDATA[<p>Сьогодні, шановний читачу, ми продовжимо розмову про те, як можна автоматизувати процес розробки програмного забезпечення, зменшити витрати часу на допоміжні роботи в великому колективі і сконцентруватись на власне розробці.</p>
<p>У колективі, кожен член якого працює над окремою незалежною частиною, стадія інтеграції є заключною. Саме в ній виявляються проблеми сумісності всіх компонентів системи, через це кінцева дата випуску може бути відсунута на невизначений термін. Саме на зменшення часових та трудових витрат на процес інтеграції за рахунок раннього виявлення проблем та усунення помилок та протиріч спрямовані системи неперервної інтеграції.</p>
<p><span id="more-165"></span></p>
<p>Серед таких систем найбільш популярними рішеннями з відкритим кодом є CruiseControl та Buildbot. Перший має значно розвиненішу структуру, в той час як другий є легким та простим у налаштуванні. Для початку ж проведемо невеличкий огляд можливостей, переваг та недоліків. Порівняння буде дещо незвичним: воно вестиметься в режимі &#8220;перехресного вогню&#8221;: кожна зі сторін аргументує власні переваги над конкурентом. Це є найкращий варіант для порівняння досить різних за будовою і реалізацією систем, оскільки в більшості випадків характеристики систем між собою не перетинаються.Після такого собі бліц-опитування ми підведемо підсумки у вигляді списку, для більшої наочності.</p>
<h3>На лінії вогню</h3>
<p style="float: left"><a title="CruiseControl logo" href="http://cruisecontrol.sourceforge.net"><img src="http://itblog.org.ua/wp-content/uploads/2009/01/cruisecontrol_logo.png" alt="CruiseControl logo" hspace="10" /></a></p>
<p style="float: right">
<table border="0">
<tbody>
<tr>
<td><strong>Остання версія</strong></td>
<td>2.7.3 / 16 Липня 2008</td>
</tr>
<tr>
<td><strong>Мова</strong></td>
<td>Java</td>
</tr>
<tr>
<td><strong>Сайт</strong></td>
<td><a href="http://cruisecontrol.sourceforge.net/">http://cruisecontrol.sourceforge.net/</a></td>
</tr>
<tr>
<td><strong>Ліцензія</strong></td>
<td>Модифікована ліцензія BSD</td>
</tr>
</tbody>
</table>
<hr />
<p style="float: right"><a title="BuildBot logo" href="http://buildbot.net"><img src="http://itblog.org.ua/wp-content/uploads/2009/01/buildbot_logo.png" alt="BuildBot logo" hspace="10" /></a></p>
<p style="float: left">
<table border="0">
<tbody>
<tr>
<td><strong>Остання версія</strong></td>
<td>0.7.8 / 24 Липня 2008</td>
</tr>
<tr>
<td><strong>Мова</strong></td>
<td>Python</td>
</tr>
<tr>
<td><strong>Сайт</strong></td>
<td><a href="http://buildbot.net/">http://buildbot.net/</a></td>
</tr>
<tr>
<td><strong>Ліцензія</strong></td>
<td>GPL</td>
</tr>
</tbody>
</table>
<p>Вже виходячи з мови, на якій написаний CruiseControl, ясно, що система в основному &#8220;заточена&#8221; для використання в проектах на Java. Це підтверджується і готовими обгортками для таких систем збирання ПЗ, як Ant, Maven, NAnt тощо. Тим не менше, існує можливість роботи з іншими системами через узагальнену обгортку exec. Buildbot же в свою чергу має кілька специфічних для пітонівських проектів можливостей, як наприклад, збирання яйця (Python eggs), генерація документації EPYDoc, проведення базового аналізу коду за допомогою PyFlakes. Окремим пунктом можна зазначити можливість проведення модульних тестів Perl. Зважаючи на переважне використання систем збирання, базованих на make-файлах, а також активне розповсюдження SCons(повноцінна система збирання ПЗ на Python), BuildBot містить готові обгортки для більшості таких систем. Як і у випадку з CruiseControl, можливо запустити на виконання будь-що за допомогою обгортки ShellCommand.</p>
<p>BuildBot побудований на архітектурі клієнт-сервер, що дозволяє проводити тестування на різних машинах з однією центральною інформаційною системою, а також розміщувати машини, на яких проводиться збирання, за NAT.</p>
<p>CruiseControl має розвинену систему сповіщення та чудовий графічний web-інтерфейс. BuildBot же, хоч і має не менш розвинені можливості для сповіщення, значно програє в інтерфейсі.</p>
<p>Інформаційна система CruiseControl побудована на JSP, що дозволяє інтегрувати її в будь-який Java Application Server, як Tomcat або ж інший більш легкий. Звичайно, за гнучкість треба платити, і ціною за використання Java і JSP є значне спочивання ресурсів і в багатьох великих проектах призводить до виділення окремого сервера під потреби CriuseControl. Легкий, простий, та досить примітивний web-інтерфейс у BuildBot дозволяє йому значно знизити навантаження на сервер. Використання Twisted в якості базової бібліотеки ж вимагає виділення окремого порту <em>на всіх мережевих інтерфейсах системи</em>, що є небажаним. Інтеграцію з Apache можливо виконати, використовуючи <em>http_proxy</em> модуль Apache та кілька правил файрвола для закриття портів системи назовні.</p>
<p>В наступній статті циклу я детально опишу реальний приклад використання систем неперервної інтеграції на прикладі BuildBot.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=U7yqOsX7U2U:GiFeBH_Rz6c:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=U7yqOsX7U2U:GiFeBH_Rz6c:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=U7yqOsX7U2U:GiFeBH_Rz6c:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/U7yqOsX7U2U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/165/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/165</feedburner:origLink></item>
		<item>
		<title>Автоматизація процесу розробки: системи збирання проектів</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/FJeLXYZDIGc/119</link>
		<comments>http://itblog.org.ua/post/119#comments</comments>
		<pubDate>Tue, 09 Jun 2009 22:02:23 +0000</pubDate>
		<dc:creator>Jolly Roger</dc:creator>
		
		<category><![CDATA[Програмування]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/?p=119</guid>
		<description><![CDATA[Час, коли в цивілізованому світі дешевше було найняти сотню негрів замість зробити ткацький верстат і навчити одну людину з ним працювати, давно минув. Ще пару десятиліть тому ледь не кожен працівник в сфері інформаційних технологій вважався митцем, творцем чогось надзвичайного, того, що не може зробити жодна інша людина в світі. Однак, час і прогрес не [...]]]></description>
			<content:encoded><![CDATA[<p>Час, коли в цивілізованому світі дешевше було найняти сотню негрів замість зробити ткацький верстат і навчити одну людину з ним працювати, давно минув. Ще пару десятиліть тому ледь не кожен працівник в сфері інформаційних технологій вважався митцем, творцем чогось надзвичайного, того, що не може зробити жодна інша людина в світі. Однак, час і прогрес не стоїть на місці, і поділ праці тому доказ. Замість тисяч самописних бібліотек виростають десятки, проте зручні та легкі; замість купи підходів до розв&#8217;язку задач виділяють одиниці, однак найефективніші; замість того, щоб вигадувати велосипед, використовують існуючі рішення, вносячи свій вклад в їх розвиток на ниві відкритих технологій. Ще донедавна програмісти збирали всі свої програми вручну або ж за допомогою самописних сценаріїв. Цей час пройшов.</p>
<p>В світі, що рухається неймовірними обертами, не можна даремно витрачати час. Вся рутина повинна бути автоматизована, і крапка. Якщо ви з цим не згодні, перечитайте перший абзац. Людина мусить спрямовувати розум на подолання нових проблем, а не на одноманітну купу операцій. Порахуйте, скільки процесів, які ви щодня виконуєте, можна автоматизувати, і зрозумійте, скільки часу ви витрачаєте марно.</p>
<p>Способи організації проектів, їх документації, юніт-тестів, тестів продуктивності, вражають своєю кількістю. Зазвичай кожен другий виробник більш-менш серйозного IDE, пакету програм для розробки, пропонує свій спосіб збереження файлів всередині проекту, організації процесу збирання, написання чи то генерація документації. Проблема постає у виборі інструментів, які допоможуть підвищити ефективність роботи та знизити часові витрати на її виконання. Сьогодні ми говоримо про системи збирання проектів.</p>
<p><span id="more-119"></span></p>
<p>В світі UNIX історично склалось, що більшість програм можна зібрати трьома командами:</p>
<pre>
$ ./configure
$ make
$ sudo make install
</pre>
<p>Цьому способу збирання та установки програм ми завдячуємо утиліті make. І хоча вона вже стара, як світ, однак досі популярна завдяки певній інертності розробників в виборі власних інструментів. Утиліта make оброблює т.з. Makefile - файл, що несе всі особливості процесу збирання. Однак вже тоді було зрозуміло, що писати їх вручну для великих проектів - досить марудна справа. І було винайдено autotools. Свого часу вони на порядок спростили визначення залежностей, встановлення додаткових параметрів компіляції, збирання та встановлення версій бібліотекам тощо. Таким чином, autotools на разі є найбільш відомою і популярною системою збирання програм під *NIX системи. </p>
<p>Та час ішов, і autotools стали здаватись дедалі більш заплутаними та складними. Проявились деякі недоліки: незважаючи на зручність в порівнянні зі збиранням вручну, написання навіть простих сценаріїв для генерації Makefile-у вимагали багато зайвої писанини. І ось вже нове покоління систем збирання з&#8217;являється на обрії. Одні з них слідують шляхом autotools, генеруючи сценарії для перевіреної часом make(QMake, CMake), інші ж розвиваються в напрямку власних сценаріїв збирання(SCons, Ant, Maven та ін.).</p>
<p>В цей же час проекти під сімейство ОС Windows зазвичай закріплені за проектами тих середовищ розробки, в яких вони були створені. При цьому неможливо зібрати проект не маючи відповідного середовища. З іншого боку, використання специфічних для кожного середовища файлів проектів покращує інтеграцію та інтерактивність при розробці. Ефективним способом виходу з цієї ситуації є взаємна інтеграція систем збирання та систем розробки. Так, на разі де факто стандартами для розробки Java проектів є використання Ant та Maven, управління якими інтегроване в більшість популярних середовищ розробки Java програм. Іншим способом вирішення проблеми є генерація файлів проектів для популярних середовищ розробки, що базуються на сценаріях збирання програм. Так, CMake дозволяє генерувати файли проектів для KDevelop, MS Visual Studio, звичайні Makefile, що дозволяє отримати готове до роботи середовище з найменшими витратами часу.</p>
<p>Важлива перевага використання систем збирання в проекті, що розробляється групою людей, полягає в можливості налаштуванні середовища під себе, не зачіпаючи при цьому налаштувань інших розробників.</p>
<p>Тим не менше, не одними програмами живуть системи збирання. SCons знайшла собі застосування в генерації PostScript та PDF з LaTeX-документів, що свідчить про неабияку гнучкість. Воно й зрозуміло, адже SCons фактично використовує Python-подібні сценарії для налаштування процесу збирання.</p>
<p>Таким чином, важливими вимогами до систем збирання є:</p>
<ul>
<li>простота в налаштуванні як простих, так і складних проектів</li>
<li>висока гнучкість у налаштуванні при можливості використовувати параметри за замовчуванням</li>
<li>інтеграція з популярними середовищами розробки</li>
<li>кросплатформенність</li>
</ul>
<p>В результаті вони</p>
<ul>
<li>надають можливість незалежного налаштування середовища розробки при незмінному принципі збирання</li>
<li>дозволяють збирати програми та відслідковувати залежності незважаючи на відсутність IDE</li>
<li>спрощують процес збирання проекту в цілому та окремих його частин</li>
<li>зменшують часові затрати на перевірку та збирання проекту</li>
<li>сприяють автоматизації процесу розробки</li>
</ul>
<p>Ви ще не знаєте, навіщо системи збирання проектів? Тоді ми йдемо до вас!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=FJeLXYZDIGc:v7pZTZng9mw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=FJeLXYZDIGc:v7pZTZng9mw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=FJeLXYZDIGc:v7pZTZng9mw:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/FJeLXYZDIGc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/119/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/119</feedburner:origLink></item>
		<item>
		<title>Пишемо інсталятори в Linux</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/rPdN-mKaK4Y/132</link>
		<comments>http://itblog.org.ua/post/132#comments</comments>
		<pubDate>Thu, 08 Jan 2009 23:06:59 +0000</pubDate>
		<dc:creator>Jolly Roger</dc:creator>
		
		<category><![CDATA[Howto]]></category>

		<category><![CDATA[Софт]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/?p=132</guid>
		<description><![CDATA[Мабуть, немає таких людей в середовищі Linux-користувачів, яким би не доводилося ставити закрите або комерційне програмне забезпечення. Не раз доводилось бачити &#8220;рідні&#8221; для цього виду програм інсталятори: графічні чи консольні, але завжди своєрідні. І поширюється програма разом з інсталятором в одному сценарії для командного інтерпретатора. А чи може хто-небудь написати власну програму-інсталятор, налаштувати її під [...]]]></description>
			<content:encoded><![CDATA[<p>Мабуть, немає таких людей в середовищі Linux-користувачів, яким би не доводилося ставити закрите або комерційне програмне забезпечення. Не раз доводилось бачити &#8220;рідні&#8221; для цього виду програм інсталятори: графічні чи консольні, але завжди своєрідні. І поширюється програма разом з інсталятором в одному сценарії для командного інтерпретатора. А чи може хто-небудь написати власну програму-інсталятор, налаштувати її під себе? . Сьогодні, шановний читачу, ми навчимося писати інсталятори для UNIX.</p>
<p><span id="more-132"></span></p>
<p>Однак, перед тим, як продовжити, слід усвідомити наступне:</p>
<p><strong>Цей приклад описаний виключно в навчальних цілях! Використовуйте його лиш у випадках крайньої необхідності!</strong></p>
<p><strong>Якщо Ви хочете поширювати власну програму для Linux &#8212; використовуйте стандартні способи поширення програмного забезпечення у відповідних дистрибутивах. Користувачі будуть Вам дуже вдячні.<br />
</strong></p>
<h3>Інсталятор зсередини</h3>
<p>Важливо зрозуміти, яким чином працює більшість інсталяторів. Типова програма для встановлення певного програмного забезпечення складається з основних двох частин: архіву з файлами цього програмного забезпечення та сценаріїв установки та видалення. Відповідно, і процес установки теж складається з двох етапів &#8212; встановлення відповідних файлів та налаштування робочого середовища. Процес видалення програмного забезпечення виконується в зворотньому порядку. Для реалізації цих підходів необхідно розробити певну структуру каталогів, наприклад, як на малюнку:</p>
<div id="attachment_133" class="wp-caption aligncenter" style="width: 295px"><a href="http://itblog.org.ua/wp-content/uploads/2008/11/structure.png"><img class="size-medium wp-image-133" title="Directory structure" src="http://itblog.org.ua/wp-content/uploads/2008/11/structure.png" alt="Структура пакету" width="285" height="272" /></a><p class="wp-caption-text">Структура директорій пакету</p></div>
<p>З малюнку можна зрозуміти, що файли, які несуть службову інформацію щодо пакету, виконують ініціалізацію та очистку середовища, знаходяться в директорії <em>package</em>. Всі інші директорії і є файлами самого програмного забезпечення. Надалі будемо опиратись на вище вказану структуру каталогів, і саме так буде виглядати свіжевстановлена нами програма.</p>
<p>Після того, як програма-інсталятор розпакувала свій вміст в задану директорію, вона запускає ініціалізаційний сценарій, який в нашому випадку зватиметься <em>package/install.sh</em> (тут і надалі всі імена файлів вказуватимуться відповідно до кореневої директорії встановленого проекту). В ході роботи встановлена нами програма може змінювати змінні середовища, створювати додаткові файли тощо. Всіма цими клопотами має займатись сценарій видалення <em>package/uninstall.sh</em>. А для того, щоб він знав, які файли були встановлені, на етапі установки буде створений список файлів <em>package/list</em>. Ось такий собі невеличкий огляд циклу життя програми: від установки і до видалення.</p>
<p>Перевівши погляд на інсталятори, які складаються з всього лиш одного сценарію командної оболонки, завжди дивуєшся, як можна покласти архів, який по суті є бінарним форматом, всередину текстового, яким є наш інсталятор. Все виявилося досить простим: достатньо використати base64- або UU-перетворення, і ось, наш архів записаний самими лише цифро-буквеними символами, або ж з доданням спеціальних символів. Не можна забувати і про зворотній бік цього перетворення - збільшення розміру файлу, так що пошук оптимального варіанту перетворення ще не закритий.</p>
<h3>Від теорії до практики</h3>
<p>Тепер, коли цілі і методи нам відомі, пора б зайнятись власне інсталятором. Перекодуванням файлів в base64, як і в UU-code, займається утиліта <em>uuencode</em>. ЇЇ аналог для зворотнього перетворення &#8212; <em>uudecode</em>. Отже, для того, щоб отримати перекодований варіант архіву, створеного з поточної директорії, достатньо виконати команду:</p>

<div class="wp_syntax"><div class="code"><pre class="bash bash" style="font-family:monospace;"> $ <span style="color: #c20cb9; font-weight: bold;">tar</span> <span style="color: #660033;">-c</span> . | <span style="color: #c20cb9; font-weight: bold;">bzip2</span> <span style="color: #660033;">-z</span> | uuencode - <span style="color: #000000; font-weight: bold;">&gt;</span> decoded_archive</pre></div></div>

<p>Тепер, коли ми знаємо, як записати архів всередині текстового файлу, достатньо обрамити його відповідними керуючими структурами, щоб отримати готовий інсталятор. Слід зауважити одну цікаву технічну особливість. Як відомо, в тій самій перекодованій формі base64 або UU-code пересилаються поштою файли в двійковому форматі. Коли декодер <em>uudecode</em> читає файл, він відкидає все, що не стосується закодованих даних. Отже, ми просто згодуємо весь наш інсталятор декодеру, уникнувши при цьому попереднє повне завантаження архіву в оперативну пам&#8217;ять. Але генерувати подібні сценарії &#8220;вручну&#8221; &#8212; справа не з приємних. Тому в якості подарунку тут буде запропонований варіант генератора подібних інсталяторів. Він здатен:</p>
<ol>
<li> Працювати в інтерактивному режимі</li>
<li> Генерувати типові інсталяційні та деінсталяційні скрипти, або використовувати вже готові, якщо такі існують.</li>
</ol>
<p>Отже, почнемо його розбір. Як і кожен сценарій, наш починається з визначення інтерпретатора, або так званого &#8220;sha-bang&#8221; рядка та невеличкої документації щодо використання самого скрипта:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># package.sh - tool for creating self-extracting and self-installing packages.</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># SYNOPSIS</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># package.sh DIR [NAME]</span>
<span style="color: #666666; font-style: italic;">#       creates a package from directory DIR with name NAME</span>
<span style="color: #666666; font-style: italic;"># </span>
<span style="color: #666666; font-style: italic;"># package.sh uses tar, uuencode and gzip to generate a package. It generates </span>
<span style="color: #666666; font-style: italic;"># installing and uninstalling scripts in DIR/package directory to provide</span>
<span style="color: #666666; font-style: italic;"># additional flexibility for users. These files (install.sh and uninstall.sh)</span>
<span style="color: #666666; font-style: italic;"># are not generated if exist.</span></pre></td></tr></table></div>

<p>Для зручності кожна окрема дія буде виділена в функцію. Оскільки всі службові сценарії лежатимуть в наперед відомій директорії <em>package</em>, то з них і почнемо:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="bash bash" style="font-family:monospace;">generate_install_script<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
<span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #000000; font-weight: bold;">&lt;</span> EOF
<span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #666666; font-style: italic;"># This is a simple installer script generated by package.sh - simple self-extracting</span>
<span style="color: #666666; font-style: italic;"># and self-installing package creator</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>PWD/package&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;This script must be run from the directory where package is installed&quot;</span>
        <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># TODO: Write your installation operations here.</span>
&nbsp;
EOF
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></td></tr></table></div>

<p>Сценарій видалення є дещо цікавішим. Оскільки список встановлених файлів знаходиться в <em>package/list</em>, то необхідно пройти весь список, вилучаючи вказані файли з системи. Щоб мати можливість вилучити не лише файли, а й директорії, при цьому залишаючи ті, які містять файли, що не входять до пакету, слід пройти цей список знизу вверх, використовуючи команду <em>rmdir</em> для директорій.
</pre>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
</pre></td><td class="code"><pre class="bash bash" style="font-family:monospace;">generate_uninstall_script<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
<span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #000000; font-weight: bold;">&lt;</span> EOF
<span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #666666; font-style: italic;"># This is a simple uninstaller script generated by package.sh - simple self-extracting</span>
<span style="color: #666666; font-style: italic;"># and self-installing package creator</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>PWD/package&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;This script must be run from the directory where package is installed&quot;</span>
        <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">tac</span> package<span style="color: #000000; font-weight: bold;">/</span>list | <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #c20cb9; font-weight: bold;">read</span> FILE
        <span style="color: #000000; font-weight: bold;">do</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>FILE&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span> ; <span style="color: #000000; font-weight: bold;">then</span>
                <span style="color: #c20cb9; font-weight: bold;">rmdir</span> \<span style="color: #007800;">$FILE</span> <span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">&gt;/</span>dev<span style="color: #000000; font-weight: bold;">/</span>null
        <span style="color: #000000; font-weight: bold;">else</span>
                <span style="color: #c20cb9; font-weight: bold;">rm</span> \<span style="color: #007800;">$FILE</span>
        <span style="color: #000000; font-weight: bold;">fi</span>
        <span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">rmdir</span> package
&nbsp;
<span style="color: #7a0874; font-weight: bold;">exit</span> 0;
EOF
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></td></tr></table></div>

<p>Тепер черга за основним скриптом інсталятора. Саме на нього покладається основна задача видобування файлів з архіву, генерації списку файлів та первинної ініціалізації нашого пакету, через це його будова містить додаткові перевірки вхідних аргументів, виведення помилок в роботі до <em>stderr</em> тощо. окрім того, в разі відсутності будь-яких вхідних аргументів сценарій дозволяє в інтерактивному режимі вказати цільову директорію. Нижче наведений код для тіла інсталятора:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
</pre></td><td class="code"><pre class="bash bash" style="font-family:monospace;">package_installer<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
<span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #000000; font-weight: bold;">&lt;</span> EOF
<span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Package installation script. </span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span> 
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
        <span style="color: #000000; font-weight: bold;">then</span>
                <span style="color: #007800;">TARGETDIR</span>=<span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>1&quot;</span>
        <span style="color: #000000; font-weight: bold;">else</span>
                <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Directory does not exist&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>stderr
                <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>;
        <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Please, specify target directory[default is <span style="color: #000099; font-weight: bold;">\$</span>PWD]: &quot;</span>
        <span style="color: #c20cb9; font-weight: bold;">read</span> TARGETDIR
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;.&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
        <span style="color: #000000; font-weight: bold;">then</span> 
                <span style="color: #007800;">TARGETDIR</span>=<span style="color: #ff0000;">&quot;.&quot;</span>
        <span style="color: #000000; font-weight: bold;">else</span>
                <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>TARGETDR&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
                <span style="color: #000000; font-weight: bold;">do</span>
                        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Directory does not exist.&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>stderr
                        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Please, specify target directory&quot;</span>
                        <span style="color: #c20cb9; font-weight: bold;">read</span> TARGETDIR 
                <span style="color: #000000; font-weight: bold;">done</span>
        <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #007800;">FILELIST</span>=\<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">mktemp</span>\<span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Extracting archive contents. This may take a while..&quot;</span>
<span style="color: #c20cb9; font-weight: bold;">cat</span> \$0 | uudecode | <span style="color: #c20cb9; font-weight: bold;">bzip2</span> <span style="color: #660033;">-dc</span> | <span style="color: #c20cb9; font-weight: bold;">tar</span> <span style="color: #660033;">-xvkC</span> \<span style="color: #007800;">$TARGETDIR</span> <span style="color: #000000; font-weight: bold;">&gt;</span> \<span style="color: #007800;">$FILELIST</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>TARGETDIR/package/list&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> \<span style="color: #007800;">$TARGETDIR</span><span style="color: #000000; font-weight: bold;">/</span>package<span style="color: #000000; font-weight: bold;">/</span>list 
<span style="color: #c20cb9; font-weight: bold;">cat</span> \<span style="color: #007800;">$FILELIST</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> \<span style="color: #007800;">$TARGETDIR</span><span style="color: #000000; font-weight: bold;">/</span>package<span style="color: #000000; font-weight: bold;">/</span>list
<span style="color: #c20cb9; font-weight: bold;">rm</span> \<span style="color: #007800;">$FILELIST</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-ne</span> <span style="color: #ff0000;">&quot;Done.<span style="color: #000099; font-weight: bold;">\\</span>nRunning installation script..&quot;</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> \<span style="color: #007800;">$TARGETDIR</span>
package<span style="color: #000000; font-weight: bold;">/</span>install.sh
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-ne</span> <span style="color: #ff0000;">&quot;Done.<span style="color: #000099; font-weight: bold;">\n</span>Do you want to remove the installer?(y/N) &quot;</span>
<span style="color: #c20cb9; font-weight: bold;">read</span> ANSWER
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\$</span>ANSWER&quot;</span> == <span style="color: #ff0000;">&quot;y&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span> 
        <span style="color: #c20cb9; font-weight: bold;">rm</span> \$0;
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Done. Enjoy!&quot;</span>
<span style="color: #7a0874; font-weight: bold;">exit</span> 0;
&nbsp;
EOF
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></td></tr></table></div>

<p>Ну ось, базові три частини, необхідні для інсталяційного пакета, готові. Тепер черга за генератором. Він в свою чергу повинен створити інсталяційні та деінсталяційні скрипти, якщо необхідно, заархівувати цільову директорію разом зі службовими скриптами і об&#8217;єднати код інсталятора  з закодованим тілом архіву. При цьому слід передбачити необхідні дії у випадку виключних ситуацій, як, наприклад створення файлу пакету з вже існуючим іменем. В результаті тіло генератора матиме вигляд:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
</pre></td><td class="code"><pre class="bash bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># Generator main part begins here</span>
<span style="color: #007800;">DIR</span>=<span style="color: #007800;">$PWD</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #000000; font-weight: bold;">then</span> 
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
        <span style="color: #000000; font-weight: bold;">then</span>
                <span style="color: #007800;">TARGETDIR</span>=<span style="color: #ff0000;">&quot;$1&quot;</span>
        <span style="color: #000000; font-weight: bold;">else</span>
                <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Directory does not exist&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>stderr
                <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>;
        <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Please, specify target directory[default is $PWD]: &quot;</span>
        <span style="color: #c20cb9; font-weight: bold;">read</span> TARGETDIR
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;$TARGETDIR&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
        <span style="color: #000000; font-weight: bold;">then</span> 
                <span style="color: #007800;">TARGETDIR</span>=<span style="color: #ff0000;">&quot;.&quot;</span>
        <span style="color: #000000; font-weight: bold;">else</span>
                <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;$TARGETDR&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>
                <span style="color: #000000; font-weight: bold;">do</span>
                        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Directory does not exist.&quot;</span> <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>stderr
                        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Please, specify target directory&quot;</span>
                        <span style="color: #c20cb9; font-weight: bold;">read</span> TARGETDIR 
                <span style="color: #000000; font-weight: bold;">done</span>
        <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Creating scripts directory if not exist</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">&quot;$TARGETDIR/package&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #c20cb9; font-weight: bold;">mkdir</span> <span style="color: #007800;">$TARGETDIR</span><span style="color: #000000; font-weight: bold;">/</span>package
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;"># Generating installation script if not specified by user.</span>
<span style="color: #007800;">INSTALLSCRIPT</span>=<span style="color: #ff0000;">&quot;$TARGETDIR/package/install.sh&quot;</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;$TARGETDIR/package/install.sh&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Generating installer script..&quot;</span>
        generate_install_script <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #007800;">$INSTALLSCRIPT</span>
        <span style="color: #c20cb9; font-weight: bold;">chmod</span> a+x <span style="color: #007800;">$INSTALLSCRIPT</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Done.&quot;</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;"># Generating uninstallation script if not specified by user.</span>
<span style="color: #007800;">UNINSTALLSCRIPT</span>=<span style="color: #ff0000;">&quot;$TARGETDIR/package/uninstall.sh&quot;</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #000000; font-weight: bold;">!</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;$UNINSTALLSCRIPT&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Generating uninstaller script..&quot;</span>
        generate_uninstall_script <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #007800;">$UNINSTALLSCRIPT</span>
        <span style="color: #c20cb9; font-weight: bold;">chmod</span> a+x <span style="color: #007800;">$UNINSTALLSCRIPT</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Done.&quot;</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;Compressing data. This may take a while..&quot;</span>
<span style="color: #007800;">DATA</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">mktemp</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$TARGETDIR</span>
<span style="color: #c20cb9; font-weight: bold;">tar</span> <span style="color: #660033;">-cf</span> -  . | <span style="color: #c20cb9; font-weight: bold;">bzip2</span> <span style="color: #660033;">-9z</span> | uuencode - <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #007800;">$DATA</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$DIR</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#Generating the final package and naming it as user desires.</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-ne</span> <span style="color: #ff0000;">&quot;Done.<span style="color: #000099; font-weight: bold;">\n</span>Generating package..&quot;</span>
<span style="color: #007800;">PACKAGE</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">mktemp</span> <span style="color: #660033;">-p</span> . package.sh.XXXXXXX<span style="color: #000000; font-weight: bold;">`</span>
package_installer <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #007800;">$PACKAGE</span>
<span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #007800;">$DATA</span> <span style="color: #000000; font-weight: bold;">&gt;&gt;</span> <span style="color: #007800;">$PACKAGE</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-ne</span> <span style="color: #ff0000;">&quot;Done.<span style="color: #000099; font-weight: bold;">\n</span>Removing temporary files..&quot;</span>
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #007800;">$DATA</span>
&nbsp;
<span style="color: #007800;">PACKAGENAME</span>=<span style="color: #ff0000;">&quot;&quot;</span>
<span style="color: #666666; font-style: italic;"># Setting up the package name</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;$2&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #007800;">PACKAGENAME</span>=$<span style="color: #000000;">2</span>
<span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #007800;">PACKAGENAME</span>=<span style="color: #ff0000;">&quot;`basename $TARGETDIR`.sh&quot;</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># If the same file is aready exist - ask user</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-f</span> <span style="color: #ff0000;">&quot;$PACKAGENAME&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-ne</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>File $PACKAGENAME already exists. Overwrite?(y/N) &quot;</span>
        <span style="color: #c20cb9; font-weight: bold;">read</span> ANSWER
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;$ANSWER&quot;</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">&quot;y&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
                <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>;
        <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #000000; font-weight: bold;">else</span>
        <span style="color: #c20cb9; font-weight: bold;">mv</span> <span style="color: #ff0000;">&quot;$PACKAGE&quot;</span> <span style="color: #ff0000;">&quot;$PACKAGENAME&quot;</span>
        <span style="color: #007800;">PACKAGE</span>=<span style="color: #007800;">$PACKAGENAME</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">chmod</span> a+x <span style="color: #007800;">$PACKAGE</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;Done.<span style="color: #000099; font-weight: bold;">\n</span>Enjoy!&quot;</span>
<span style="color: #7a0874; font-weight: bold;">exit</span> 0;</pre></td></tr></table></div>

<p>Ось генератор і готовий. І хоча він досить примітивний, однак на живому прикладі дозволяє побачити деякі з можливостей всім відомого командного інтерпретатора. Наостанок лиш хочу всіх поздоровити з минулими святами, і нехай цей рік принесе радість пізнання невідомого та успіх!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=rPdN-mKaK4Y:iOPDdWYh5yM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=rPdN-mKaK4Y:iOPDdWYh5yM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=rPdN-mKaK4Y:iOPDdWYh5yM:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/rPdN-mKaK4Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/132/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/132</feedburner:origLink></item>
		<item>
		<title>Теми в Gmail - що далі?</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/eXJ9L-eRq5U/144</link>
		<comments>http://itblog.org.ua/post/144#comments</comments>
		<pubDate>Fri, 21 Nov 2008 09:38:31 +0000</pubDate>
		<dc:creator>FerR0zer</dc:creator>
		
		<category><![CDATA[Інтернет]]></category>

		<category><![CDATA[gmail]]></category>

		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/?p=144</guid>
		<description><![CDATA[Сьогодні в GMail 2 з’явилася підтримка тем. Причому деякі теми змінюються в залежності від часу дня та погоди на вулиці, для чого при виборі нової теми пропонують вказати місцезнаходження. Це значно збільшить і так значну інтерактивність Гугловської пошти.
Ось, наприклад, як виглядає тема &#8220;Пляж&#8221; в той же час для Бостнону та Києва. 

В темі &#8220;Дерево&#8221;, наприклад, [...]]]></description>
			<content:encoded><![CDATA[<p>Сьогодні в GMail 2 з’явилася підтримка тем. Причому деякі теми змінюються в залежності від часу дня та погоди на вулиці, для чого при виборі нової теми пропонують вказати місцезнаходження. Це значно збільшить і так значну інтерактивність Гугловської пошти.</p>
<p>Ось, наприклад, як виглядає тема &#8220;Пляж&#8221; в той же час для Бостнону та Києва. </p>
<p><span id="more-144"></span></p>
<div id="attachment_145" class="wp-caption alignright" style="width: 160px"><a href="http://itblog.org.ua/wp-content/uploads/2008/11/beach_boston.png"><img class="size-thumbnail wp-image-145 alignright" title="Тема GMail Beach для Бостону" src="http://itblog.org.ua/wp-content/uploads/2008/11/beach_boston-150x150.png" alt="Тема GMail Beach для Бостону" width="150" height="150" /></a><p class="wp-caption-text">Тема GMail Beach для Бостону</p></div>
<div id="attachment_146" class="wp-caption alignright" style="width: 160px"><a href="http://itblog.org.ua/wp-content/uploads/2008/11/beach_kyiv.png"><img class="size-thumbnail wp-image-146" title="beach_kyiv" src="http://itblog.org.ua/wp-content/uploads/2008/11/beach_kyiv-150x150.png" alt="Тема GMail Beach для Києва" width="150" height="150" /></a><p class="wp-caption-text">Тема GMail Beach для Києва</p></div>
<p>В темі &#8220;Дерево&#8221;, наприклад, для Бостону йшов проливний дощ.</p>
<p>Що ж буде наступним?</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=eXJ9L-eRq5U:giHBTeTfUZQ:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=eXJ9L-eRq5U:giHBTeTfUZQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=eXJ9L-eRq5U:giHBTeTfUZQ:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/eXJ9L-eRq5U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/144/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/144</feedburner:origLink></item>
		<item>
		<title>Opera українською</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/opg-Z5iXSY0/123</link>
		<comments>http://itblog.org.ua/post/123#comments</comments>
		<pubDate>Fri, 10 Oct 2008 13:09:44 +0000</pubDate>
		<dc:creator>FerR0zer</dc:creator>
		
		<category><![CDATA[Софт]]></category>

		<category><![CDATA[opera]]></category>

		<category><![CDATA[переклади]]></category>

		<category><![CDATA[українська]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/?p=123</guid>
		<description><![CDATA[Встановив сьогодні Оперу 9.60. При встановленні радує око - дефолтно пропонує українську мову! В рядку ідентифікації - теж українська.  Серед інших змін - оновлений поштовий клієнт, бокова панель. Також з’явився Scroll Marker - смуга, яка показує положення екрану до прокрутки. Може виявитись зручною штукою для любителів читати книги та багатосторінкові статті.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://itblog.org.ua/wp-content/uploads/2008/10/opera960.jpg"><img class="alignright size-medium wp-image-124" title="Opera 9.60 Українською" src="http://itblog.org.ua/wp-content/uploads/2008/10/opera960.jpg" alt="" width="300" height="238" /></a>Встановив сьогодні Оперу 9.60. При встановленні радує око - дефолтно пропонує українську мову! В рядку ідентифікації - теж українська.  Серед інших <a href="http://www.opera.com/docs/changelogs/windows/960/">змін</a> - оновлений поштовий клієнт, бокова панель. Також з’явився Scroll Marker - смуга, яка показує положення екрану до прокрутки. Може виявитись зручною штукою для любителів читати книги та багатосторінкові статті.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=opg-Z5iXSY0:oiDX5Z3xVY0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=opg-Z5iXSY0:oiDX5Z3xVY0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=opg-Z5iXSY0:oiDX5Z3xVY0:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/opg-Z5iXSY0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/123/feed</wfw:commentRss>
		<media:content url="http://feedproxy.google.com/~r/Itblog-ua/~5/fGJVcrVImHE/" type="application/xml" /><feedburner:origLink>http://itblog.org.ua/post/123</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Itblog-ua/~5/fGJVcrVImHE/" length="-1" type="application/xml" /><feedburner:origEnclosureLink>http://www.opera.com/docs/changelogs/windows/960/</feedburner:origEnclosureLink></item>
		<item>
		<title>Цікава новина від Brainbench</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/LhICDATad5c/120</link>
		<comments>http://itblog.org.ua/post/120#comments</comments>
		<pubDate>Thu, 28 Aug 2008 19:04:54 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
		
		<category><![CDATA[Блоги]]></category>

		<category><![CDATA[brainbench]]></category>

		<category><![CDATA[certification]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=402</guid>
		<description><![CDATA[ Щойно отримав листа від Brainbench в якому повідомляється про 85% знижку на річну підписку (annual subscription) на їх тести. Тобто рік фактично необмеженого (єдине, що не можна - це отримати від них друкований сертифікат) користування їх тестами коштуватиме лише 30$. Як на мене, то це майже халява  Пропозиція діє до 15-го вересня і [...]]]></description>
			<content:encoded><![CDATA[<a href="http://brainbench.com/"><img class="alignleft" title="Brainbench logo" src="http://www.brainbench.com/avmedia/images/default/bblogosmall.gif" alt="" width="170" height="46" align="left" /></a> Щойно отримав листа від <a href="http://brainbench.com/">Brainbench</a> в якому повідомляється про 85% знижку на річну підписку (annual subscription) на їх тести. Тобто рік фактично необмеженого (єдине, що не можна - це отримати від них друкований сертифікат) користування їх тестами коштуватиме лише 30$. Як на мене, то це майже халява <img class="wp-smiley" src="http://graywolf.org.ua/wp-includes/images/smilies/icon_smile.gif" alt=":)" /> Пропозиція діє до 15-го вересня і для обмеженої кількості країн: Латвія, Литва, Малайзія, Пакістан, Румунія, Росія, <em>Україна</em>, Узбекістан, В’єтнам. Більш детально можна дізнатись на <a href="http://www.brainbench.com/xml/bb/landing/offer/promotion.xml?contentId=2414">їх сторінці присвяченій цій акції</a>.

Думаю на початку вересня, як отримаю зарплатню скористаюся можливістю. Все-таки, багато київських роботодавців практикують Brainbench-тести як елемент оцінки при прийомі на роботу, та й самому цікаво буде періодично оцінювати свої знання.
<div class="meta"></div><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=LhICDATad5c:pDCqcfRfwDI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=LhICDATad5c:pDCqcfRfwDI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=LhICDATad5c:pDCqcfRfwDI:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/LhICDATad5c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/120/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/120</feedburner:origLink></item>
		<item>
		<title>Інтернет початку XXI сторіччя. Lifestreaming або соціальні агрегатори</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/9Cvf2K4vS8k/118</link>
		<comments>http://itblog.org.ua/post/118#comments</comments>
		<pubDate>Thu, 14 Aug 2008 21:51:31 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
		
		<category><![CDATA[Блоги]]></category>

		<category><![CDATA[flickr]]></category>

		<category><![CDATA[friendfeed]]></category>

		<category><![CDATA[twitter]]></category>

		<category><![CDATA[web]]></category>

		<category><![CDATA[web 2.0]]></category>

		<category><![CDATA[соціальні мережі]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=371</guid>
		<description><![CDATA[Те, про що піде мова сьогодні, являється однією з найсмачніших інтернет-новинок, які принісли останні роки. Хоча, звісно, ці сервіси не з&#8217;явилися б не будь всих попередніх, які я вже згадував в рамках цього циклу статей: мікро- та звичайних блогів, соціальних мереж, соціальних новин, контент-хостерів, тощо. Зате вони ставлять зручність користування цим всим на інший рівень [...]]]></description>
			<content:encoded><![CDATA[<img src="http://friendfeed.com/static/images/logo-b.png" alt="" width="234" height="53" align="left" />Те, про що піде мова сьогодні, являється однією з найсмачніших інтернет-новинок, які принісли останні роки. Хоча, звісно, ці сервіси не з’явилися б не будь всих попередніх, які я вже згадував в рамках цього циклу статей: мікро- та звичайних блогів, соціальних мереж, соціальних новин, контент-хостерів, тощо. Зате вони ставлять зручність користування цим всим на інший рівень і відкривають деякі нові можливості. Ідея соціальних агрегаторів проста: вони збирають інформацію про вашу активність в мережі та подають її одним змішаним потоком. З’явилася вона порівняно недавно, коли у вжиток увійшло поняття “мережевої втоми” (“network fatigue”), одним з елементів якої вважається необхідність реєструватись на та відвідувати купу сайтів для того, щоб відстежувати, що роблять або чим цікавляться ваші “друзі” (в лапках, бо мається на увазі в мережевому сенсі) на різних сайтах та мережах. Тобто поясню на прикладі: ваш друг публікує фотки за допомогою Google Picasa, розшарює новини через Google Reader, пише щось в персональний блог, користується мікроблоггінгом і т.д., і т.п. <a href="http://www.scrnshots.com/users/graywolf/screenshots/46584"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/46584/ff1_med_rect.jpg" alt="" align="right" /></a>Для того, щоб бути в курсі останніх змін вам треба або періодично заходити на всі ці сайти аби перевірити чи не з’явилось що новеньке (те ще збочення, погодьтесь), або підписатись на відповідну RSS (благо, всі сучасні сайти дозволяють це зробити). Фактично більшість соціальних агрегаторів типу <a href="http://pulse.plaxo.com/">Plaxo Pulse</a>, <a href="http://iminta.com/">Iminta</a> та інших лише це і роблять — просто збирають інформацію докупи. Хоч і не завжди все через RSS — часто через API відповідних сервісів, які надають більше можливостей, завдяки чому ці сервіси все ж більш гнучкі й потужні, аніж просто купа RSS. Та все одно це занадто примітивно і… несоціально <img src="http://graywolf.org.ua/wp-includes/images/smilies/icon_smile.gif" alt=")" /> Якось по-дурному виходить: служба агрегації соціальних сайтів сама не є такою. Тому я цього разу відійду від попередньої практики опису декількох конкуруючих ресурсів і зупинюсь на тому, який вважаю безсумнівним лідером в цій сфері, який залишив інших далеко позаду. Мова піде про <a href="http://friendfeed.com">FriendFeed</a> — стартап, який був розроблений не ким-небудь, а колишніми співробітниками компанії Google, що займали там далеко не останні позиції.

Отож, як писалось вище, основна робота ФрендФіду збирати докупи вашу активність в Мережі. Там є певний набір сервісів, що підтримуються на рівні API, а все інше можна при бажанні додати як підписку типу “Блог” (насправді це не обов’язкоко має бути блог - це скоріше звичайний RSS-агрегатор), вказавши відповідну RSS-стрічку. Таким чином ви реєструєте свою активність з різних сайтів у ФФ, а інші користувачі, кому цікава ваша персона, в свою чергу можуть підписатися на стрічку з нею. Величезна кількість підтримуваних сервісів (див. скріншот) вже зараз вирізняє його з-поміж конкурентів, але не лише цим він цікавий.

<a href="http://www.scrnshots.com/users/graywolf/screenshots/46588"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/46588/ff2.jpg" alt="" /></a>

По-перше, там є можливість коментувати цю активність (буває такі розгортаються суперечки, що блоги відпочивають <img src="http://graywolf.org.ua/wp-includes/images/smilies/icon_smile.gif" alt=")" /> ) та додавати в “Улюблене”. І коментарі там — це не просто данина моді, а дуже зручна річ, коли вам хочеться прокоментувати активність на якомусь сервісі, де ви не зареєстровані. Для мейнстрімових речей є можливість “зворотного зв’язку”. Наприклад, коментарі до дописів в Twitter’і можна відправляти теж як твіти-відповіді (звісно, для цього вже треба бути зареєстрованим на відповідному сайті, але принаймні заходити на нього не треба та й виглядає обговорення зручніше). Щодо додавання у Favorites, то тут теж прикольно зроблено: з транзитивністю операції. Тобто, наприклад, користувач A читає користувача B, а B в свою чергу — C, але A нічого не знає про C, та коли користувач B додає в “Улюблене” щось зі стрічки C, то це попадає і в загальний потік користувача A, що останньому дуже і дуже зручно, бо в “Улюблене” зазвичай додають дійсно цікаві і варті уваги речі.

По-друге, можна відслідковувати активність людей не зареєстрованих на FriendFeed’і. Для цього є механізм “уявних друзів” (imaginary friend), коли ви додаєте чиюсь активність до ФФ по аналогії зі своєю власною, але використовуючи його логін чи то ідентифікатор при додаванні контенту, але ця активність не відмічається як “ваша”.

По-третє, зручний пошук. Здавалося б така дрібниця, але деякі агрегатори і цього не мають. До речі, я часто використовую FF для пошуку по прошарених дописах в Google Reader, бо він зберігає shared та starred записи лише впродовж одного місяця.

По-четверте, є тут така штука як “кімнати” (це одне останніх же нововведень), тобто своєрідні тематичні стрічки, в певному сенсі аналоги спільнот.

По-п’яте, в стрічка вашої активності може наповнюватись не лише автоматично із соціальних мереж, або RSS. Можна і просто залишити повідомлення, посилання на зовнішній ресурс чи картинки вручну — потрібно лише перетягти на панель відповідну “кнопку”.

<a href="http://www.scrnshots.com/users/graywolf/screenshots/46592"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/46592/alert_thingy_med_rect.jpg" alt="" align="right" /></a> Ну і ще багато всього. Його розробники подумали про багато приємних дрібниць. Припустимо, якщо ви довго не мали доступу до Інтернету, а “друзів” у вас багато, то у FF є спеціальний режим перегляду “найцікавіше за день/тиждень/місяць”, коли не потрібно буде перечитувати по декілька сторінок інформації, далеко не вся з якої може бути вам цікава, а так можна вже одразу відфільтрувати. Звісно, як і у кожного поважного стартапу у нього є API, завдяки чому було розроблено масу додатків. В тому числі з того чим я активно користуюсь: AIR-клієнт <a href="http://alertthingy.com/">Alert Thingy</a> (з підтримкою публікації не лише у FriendFeed, а також в Twitter та Flickr) та плагін-віджет для Wordpress.

Мну особисто завдячує ФрендФіду як одному з джерел цікавої інформації за рахунок його системи обміну цікавинками, а з іншого - економією часу на відвідуванні інших сайтів (фактично останнім часом ранковий перегляд новин звівся до перегляду FF-стрічки, пари форумів та інколи Google Reader; останній рідко, бо досить багато часу витрачається). До речі, цікаво що активно викорситовувати я його став лише через кілька місяців після реєстрації. Тоді навіть знаючи про нього багато з того, що написано вище я не розумів навіщо його потрібно. А зараз це один з основних сайтів на які я заходжу. Отаке.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=9Cvf2K4vS8k:ORpidrMjZXI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=9Cvf2K4vS8k:ORpidrMjZXI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=9Cvf2K4vS8k:ORpidrMjZXI:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/9Cvf2K4vS8k" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/118/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/118</feedburner:origLink></item>
		<item>
		<title>Управління проектами з Trac</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/83_imNHJBY8/109</link>
		<comments>http://itblog.org.ua/post/109#comments</comments>
		<pubDate>Thu, 07 Aug 2008 23:11:08 +0000</pubDate>
		<dc:creator>Jolly Roger</dc:creator>
		
		<category><![CDATA[Howto]]></category>

		<category><![CDATA[Програмування]]></category>

		<category><![CDATA[Софт]]></category>

		<category><![CDATA[git]]></category>

		<category><![CDATA[python]]></category>

		<category><![CDATA[trac]]></category>

		<category><![CDATA[консоль]]></category>

		<category><![CDATA[управління проектами]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/post/109</guid>
		<description><![CDATA[Задача: отримати багатоцільове open-source середовище для управління проектами з web-інтерфейсом, підтримкою Git та БД PostgreSQL, автентифікацією через LDAP.
Обираємо систему управління проектами
За інформацією для роздумів гугл нас привів на сторінку з вікіпедії. Як бачимо, вибір у нас досить великий. Вибрати з них що-небудь по собі з виконанням більшості критеріїв досить нескладно. Однак підтримку Git має в [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Задача:</strong> отримати багатоцільове open-source середовище для управління проектами з web-інтерфейсом, підтримкою Git та БД PostgreSQL, автентифікацією через LDAP.</p>
<h4>Обираємо систему управління проектами</h4>
<p>За інформацією для роздумів гугл нас привів на <a href="http://en.wikipedia.org/wiki/List_of_project_management_software">сторінку</a> з вікіпедії. Як бачимо, вибір у нас досить великий. Вибрати з них що-небудь по собі з виконанням більшості критеріїв досить нескладно. Однак підтримку Git має в своїй реалізації лиш один проект &#8212; Trac, про який і йтиме мова далі.</p>
<h4>Чому Trac</h4>
<p style="float: left"> <a href="http://trac.edgewall.org/" title="Trac logo"><img src="http://itblog.org.ua/wp-content/uploads/2008/08/trac_logo.png" ilo-full-src="http://itblog.org.ua/wp-content/uploads/2008/08/trac_logo.png" alt="Trac logo" hspace="10" /></a></p>
<table>
<tr>
<td><strong>Версія</strong></td>
<td>0.11</td>
</tr>
<tr>
<td><strong>Мова</strong></td>
<td>Python</td>
</tr>
<tr>
<td><strong>Сайт</strong></td>
<td><a href="http://trac.edgewall.org/">http://trac.edgewall.org/</a></td>
</tr>
<tr>
<td><strong>Ліцензія</strong></td>
<td>Модифікована ліцензія BSD</td>
</tr>
</table>
<p>Як вже було сказано, лише в нього я знайшов підтримку Git репозиторіїв. До того ж Trac має неабияку гнучкість: окрім базового набору, якого зазвичай не вистачає, купа функціоналу реалізована у вигляді плагінів, яких <a href="http://trac.edgewall.org/wiki/PluginList">тут</a> можна знайти на будь-який смак. Простий та зрозумілий з першого погляду інтерфейс, відсутність зайвих &#8220;свистілок&#8221; не може не порадувати людей, які від продукту очікують ефективну реалізацію функціоналу. Можливість адаптувати середовище на власний смак та за потребами проекту, будь то розробка програмного забезпечення, адміністрування, чи організація господарських робіт у себе на городі. Хоча незважаючи на можливість вести будь-які проекти в цій системі, все ж вона тісно інтегрована з ситемами контролю версій(Svn, Bazaar, Mercurial, Git), підсвіткою синтаксису &#8220;на льоту&#8221;(використовуються SilverLight, Enscript, а з версії 0.11 &#8212; ще й Pygments), розробкою документації (Doxygen, PyDoc, PerlDoc), і навіть системою управління тестами. Підтримка RSS-стрічок, wiki(до якої є теж купа розширень), і навіть ведення блогу додають практично всі необхідні інструменти для ведення сучасного проекту. Довершує все це добро документація по Trac, яка є в кожному новоствореному проекті на стоірнках wiki.</p>
<h4>Установка та адміністрування</h4>
<p>Ставити ми його будемо, звичайно ж, на Debian GNU/Linux, для якого поточною стабільною віткою вважається 0.10. Сподіваюсь, ви вже маєте налаштований Git репозиторій, інакше раджу взяти низький старт з <a href="http://www.kernel.org/pub/software/scm/git/docs/gittutorial.html">цієї</a> сторінки. Виконавши <tt>aptitude install apache2 libapache2-mod-python trac-core trac-git pcycopg2</tt> та встановивши залежності й додаткові пакети за бажанням переходимо власне до конфігурації.</p>
<p>Першим кроком буде створення нового проекту. Де тримати проекти &#8212; справа кожного, хоча мені більше імпонує покласти їх до <tt>/var/trac/</tt>. Для промислового розгортання буде доцільним розгортати подібні середовища в домашніх директоріях користувачів. Отже, почнемо.</p>
<pre># mkdir /var/trac
# cd /var/trac
# trac-admin myproject initenv</pre>
<p>В процесі установки система необхідно ввести деякі базові настройки, вибрати БД, з якою працюватимете, та вказати шлях до репозиторію. Якщо в якості репозиторію ви вказали Git, то система в кінці видасть попередження про відсутність його підтримки, однак все це можна сміливо ігнорувати, бо все це ми виправимо в подальших кроках.</p>
<p><a href="http://itblog.org.ua/wp-content/uploads/2008/08/trac-admin.png" title="trac-admin management utility"><img src="http://itblog.org.ua/wp-content/uploads/2008/08/trac-admin.thumbnail.png" style="float: left" alt="trac-admin management utility" hspace="10" /></a>Саме з цього моменту починають проявлятись особливості роботи з Trac: адміністрування проекту проводиться за допомогою консольної утиліти <tt>trac-admin</tt>. Отже, якщо ви не маєте доступу через SSH до свого сервера, годі й мріяти про установку цієї системи. І хоча деякі операції можливо перекласти на веб-морду, однак початкову ініціалізацію &#8212; зась. Якщо ж ви все ще з нами і вже готові до наступного кроку, то не гаймо часу.</p>
<p>Всі налаштування проекта знаходяться в одному файлі <tt>conf/trac.ini</tt> в директорії проекту. Зараз можна підправити загальні параметри проекту, однак я раджу відкласти цей крок на момент після тестового запуску проекту. Справа в тому, що будь-який згенерований проект з самого початку містить wiki-документацію, яка доступною мовою опише можливості та особливості налаштування системи. Знову повертаючись до Git, на сторінці <a href="http://trac-hacks.org/wiki/GitPlugin">GitPlugin</a> ви зможете прочитати вичерпні пояснення щодо того, яким чином організувати співпрацю Trac та Git.</p>
<p>Для успішного старту проекту необхідно отримати можливість запускати Python-івські скрипти на запит веб-сервера. Це можна реалізувати через механізм CGI, FastCGI, або ж використовуючи mod_python, що ми, власне, і зробимо:</p>
<pre>&lt;Location/projects&gt;
  SetHandler mod_python
  PythonInterpreter main_interpreter
  PythonHandler trac.web.modpython_frontend
  PythonOption TracEnvParentDir /var/trac
  PythonOption TracUriRoot /projects
&lt;/Location&gt;</pre>
<p>Вище представлений шматок конфігураційного файлу веб-сервера, який дозволить вести нам безліч проектів, що лежатимуть в <tt>/var/trac</tt> Наступні рядки ж дозволять мати один обліковий запис для всіх проектів. Даний тип автентифікації приведений лише для прикладу. Автентифікація користувачів через систему LDAP буде описана в наступних статтях.</p>
<pre>&lt;LocationMatch"/projects/[^/]+/login"&gt;
  AuthType Basic
  AuthName "Trac"
  AuthUserFile /var/trac/.htpasswd
  Require valid-user
&lt;/LocationMatch&gt;</pre>
<p>Якщо всі кроки виконані успішно, ви мусите побачити вже працюючий проект за адресою:<a href="http://localhost/projects/myproject/">http://localhost/projects/myproject/</a></p>
<h4>Додаткові плагіни</h4>
<p>Деякі з плагінів потребують особливої уваги при роботі з ними. Тут розглянуті лиш два з них, хоча насправді проблеми можуть виникнути в багатьох плагінах, функціонал яких пов&#8217;язаний з іншими системами, зокрема плагіни, що реалізують автентифікацію.</p>
<h5>GraphvizPlugin</h5>
<p><a href="http://itblog.org.ua/wp-content/uploads/2008/08/screenshot.png" title="Trac with GraphViz plugin"><img src="http://itblog.org.ua/wp-content/uploads/2008/08/screenshot.thumbnail.png" style="float: right" alt="Trac with GraphViz plugin" hspace="10" /></a>Трохи помучитись змусив мене плагін, що реалізовує inline-вставку графічного представлення інформації за допомогою graphviz. Для тих, хто все ще не може отримати зображення, підкажу основні вимоги:</p>
<ul>
<li>директорія, в якій знаходиться кеш graphviz повинна бути доступна для запису користувачем <tt>www-data</tt>, під яким запущено веб-сервер. Крім того, якщо ви використовуєте <tt>tmpfs</tt>, то не робіть директорію для кешу в <tt>/tmp</tt>, оскільки для роботи graphviz необхідне існування директорії, а при наступному ж перезавантаженні вона просто зникне.</li>
<li>необхідні пакети: <tt>graphviz</tt> та <tt>librsvg2-bin</tt></li>
</ul>
<h5>WebAdmin</h5>
<p>Для того, щоб не мати клопоту при роботі з цим плагіном, необхідно, щоб файли проекту в /var/trac/myproject були доступними користувачеві www-data для запису. Загалом же, плагін встановлюється та підключається без зайвих зусиль.</p>
<h4>Trac та PostgreSQL 8.3</h4>
<p>Якщо ви використовуєте Trac 0.10 зі стандартних пакетів Debian, то матимете клопіт з неможливістю перегляду звітів про помилки (tickets). При цьому ще й при додаванні такого звіту система може видавати помилки. Для того, щоб усунути цю помилку, необхідно змінити у файлі /usr/share/python-support/trac/trac/ticket/model.py рядок 296 з:</p>
<pre>"ORDER BY time", (self.id, str(self.id), self.id))</pre>
<p>на</p>
<pre>"ORDER BY time", (self.id, str(self.id), str(self.id)))</pre>
<p>Сподіваюсь, що за кілька днів після випуску даної статті ця порада стане непотрібною <img src='http://itblog.org.ua/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h4>Висновки</h4>
<p>Закінчуючи статтю, хочеться підбити підсумки щодо системи в цілому. Особисто я вже використовую Trac для власних проектів, тому що ця система:</p>
<ul>
<li>проста, зручна, та ефективна</li>
<li>має підтримку сучасних репозитаріїв, баз данних та прикладного програмного забезпечення</li>
<li>дуже гнучка</li>
<li>знаходиться в активній розробці</li>
</ul>
<p>Хочете переконатися в цьому самостійно? Тоді ласкаво просимо до <a href="http://www.hosted-projects.com/trac/TracDemo/Demo">http://www.hosted-projects.com/trac/TracDemo/Demo</a> , де ви зможете попрацювати з Trac без зайвого клопоту.</p>
<p>Серед недоліків даної системи щодо нашого ринку можу віднести майже відсутній хостинг з підтримкою Python та неможливість організації повного циклу життя проекту від його зародження і до закриття через веб-інтерфейс, хоча останнє скоро буде виправлене.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=83_imNHJBY8:C3vk0lNkCKM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=83_imNHJBY8:C3vk0lNkCKM:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=83_imNHJBY8:C3vk0lNkCKM:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/83_imNHJBY8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/109/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/109</feedburner:origLink></item>
		<item>
		<title>Мобілізуємо блог</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/7CfYvuB9hpw/111</link>
		<comments>http://itblog.org.ua/post/111#comments</comments>
		<pubDate>Wed, 06 Aug 2008 23:21:06 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
		
		<category><![CDATA[Блоги]]></category>

		<category><![CDATA[mobile]]></category>

		<category><![CDATA[phone]]></category>

		<category><![CDATA[web]]></category>

		<category><![CDATA[web 2.0]]></category>

		<category><![CDATA[мобільний]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=356</guid>
		<description><![CDATA[Ні, не в армію ми його будемо мобілізувати, а всього-на-всього зробимо придатним для відображення на маленьких екранах мобільних телефонів за допомогою одного цікавого стартапу під назвою MoFuse. Про потужність і надійність сервісу говорить той факт, що його використовують такі не останні в Інтернеті сайти як ReadWriteWeb, ReadBurner, Mashable та багато інших. Завдяки ньому можна зробити [...]]]></description>
			<content:encoded><![CDATA[<a href="http://graywolf.org.ua/wp-content/uploads/2008/08/mofuse-0.jpg"><img src="http://graywolf.org.ua/wp-content/uploads/2008/08/mofuse-0-160x300.jpg" alt="Мобільний сайт під управлянням MoFuse. Попередній перегляд сторінки на емуляторі." width="160" height="300" align="left" /></a>Ні, не в армію ми його будемо мобілізувати, а всього-на-всього зробимо придатним для відображення на маленьких екранах мобільних телефонів за допомогою одного цікавого стартапу під назвою <a href="http://www.mofuse.com/">MoFuse</a>. Про потужність і надійність сервісу говорить той факт, що його використовують такі не останні в Інтернеті сайти як <a href="http://www.readwriteweb.com/">ReadWriteWeb</a>, <a href="http://www.readburner.com/">ReadBurner</a>, <a href="http://mashable.com/">Mashable</a> та багато інших. Завдяки ньому можна зробити гарну мобільну версію вашого блогу всього за кілька хвилин, що я зараз і постараюсь більш-менш детально описати. Тож запускайте секундомір і починемо.
<h4>Реєстрація</h4>
Звісно, без неї нікуди. Зробити це можна прямо з <a href="http://www.mofuse.com/">головної сторінки сайту</a>. І я б не згадав про неї, якби не одне <em>але</em>: звертайте увагу на коректне заповнення поля Login (ним виступає e-mail адреса)! Справа в тому, що MoFuse не перевіряє її і тому там випадково можна ввести неправильну інформацію, що я вже і встиг зробити вранці, а потім ввечері довго не міг зайти — довелося порпатися в кеші Опери та шукати щось таке, що могло б наштовхнути на правильну адресу. Благо, таки знайшов — виявилось, що я пропустив літеру “L” при написанні домену gmail.com <img src="http://graywolf.org.ua/wp-includes/images/smilies/icon_smile.gif" alt=")" /> Так що будьте уважними.
<h4>Запускаємо мобільний сайт</h4>
<a href="http://www.scrnshots.com/users/graywolf/screenshots/42613"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/42613/mofuse-1_med_rect.jpg" align="right" /></a> Увійшовши до MoFuse в панелі керування вибираємо <a href="http://app.mofuse.com/users/new">“Launch a mobile  site”</a>. Там вам необхідно буде заповнити декілька полів типу назви сайту, вибрати його майбутню адресу (у вигляді <em>&lt;ваша назва&gt;.mofuse.mobi</em>), а також вказати RSS-джерело для наповнення сайту. Їх може бути декілька, при створенні вказується основне, а можна взагалі пропустити цей пункт поставивши відповідну галочку — це якщо ви збираєтесь зробити статичний сайт, або плануєте додати джерела пізніше. Але так як ми домовились мобілізовувати блог, то RSS нам прописати просто необхідно. Власники standalone-блогів, думаю, знають адреси своїх RSS-стрічок. Користувачі <a href="http://livejournal.com/">LiveJournal</a> мають прописати туди щось типу: “<em>http://&lt;нікнейм&gt;.livejournal.com/data/rss</em>“, а користувачі <a href="http://blogger.com/">Blogger</a> відповідно: “<em>http://&lt;нікнейм&gt;.blogspot.com/feeds/posts/default</em>“.

Професійним блоггерам варто звернути увагу на галочку “<em>You’ve read and agree to our Revenue Sharing Policy</em>”. Мова тут йде про те, що у сайту є фіча монетизації мобільного сайту шляхом додавання туди реклами <a href="https://www.google.com/adsense/">Google AdSence</a> або <a href="http://www.admob.com/">AdMob</a>, але прибуток від реклами ділитиметься між вами та MoFuse 50/50.

Ну і все. Натискаєте “<em>Launch Your Mobile Site</em>” і вуа-ля: ви маєте свій блог в мобільному Інтернеті, доступним за адресою, яку вказали в полі “Site ID (URL)”. Якщо ви перейдете по тій лінці в звичайному браузері, то побачите емулятор вікна звичайного мобільного телефону, або <a href="http://www.apple.com/iphone/">Apple iPhone</a>, в якому можна оцінити як виглядатиме ваш сайт на мобільному телефоні.

<a href="http://www.scrnshots.com/users/graywolf/screenshots/42617"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/42617/mofuse-2.jpg" align="right" /></a>
<h4>Прикрашання та контент</h4>
Але залишати сайт в такому вигляді нецікаво, адже MoFuse має ще багато цікавих можливостей гнучкого налаштування. Наприклад, власники свого доменного імені можуть зробити мобільний сайт його піддоменом (є неформальна практика робити мобільний домен у вигляді m.&gt;назва основгого сайту&lt;, тобто щось типу <a href="http://m.graywolf.org.ua/">m.graywolf.org.ua</a>). Також можна налаштувати кольорову гаму сайту та завантажити власний логотип.

Далі можна додати якийсь текст на стартовій сторінці сайту, додати  нові джерела для RSS, статичні сторінки, зовнішні посилання та віджет для коментарів, але з цим ви вже можете поекспериментувати самостійно <img src="http://graywolf.org.ua/wp-includes/images/smilies/icon_wink.gif" alt=";)" />

Щодо професійних речей, то як я вже згадував раніше, в MoFuse є вбудована можливість монетизації мобільних сайтів. Плюс до того є простенька статистика відвідувань принаймні із referer’ами (вказанням місць, звідки прийшли на ваш сайт).
<h4>Інтеграція та просування</h4>
Але і це ще не все. Погодьтесь, потенційним користувачам не зручно пам’ятати адреси вашого і мобільного блогу, і повноформатного. Для того, щоб уникнути цього можна скористатись пунктом “<em>Automatic redirect</em>”. Там знаходиться шматок PHP-коду, який потрібно вставити в код вашого сайту і який здійснюватиме перенаправлення на мобільну версію, якщо ви заходитимете з мобільного телефону. На жаль цією фічею зможуть скористатись лише власники standalone-блогів. Наприклад, користувачі Wordpress можуть вставити цей код на початку файлу теми, що відповідає за заголовок. Тим же хто користується блогхостингами типу Blogger та LiveJournal можна скористатись пунктами “<em>Mobi Badge</em>” та “<em>QR Code</em>”. В першому ви можете вибрати симпатичну картинку з посиланням на ваш мобільний блог та вставити її код потім в профілі чи ще де. Другий генерує картинку з QR-кодом для швидкого зчитування лінки в мобільним телефоном (якщо ви досі не знаєте, <a href="http://kilesa.org.ua/2008/02/12/hardlinks/">що таке QR-коди</a>, то гарний лікбез є <a href="http://kilesa.org.ua/2008/02/12/hardlinks/">тут</a>).
<h4>Післямова</h4>
Ну от і все. Просто, правда ж? Насправді зараз здається, що нікому зараз мобільні сайти не потрібні, але, ІМХО, варто призвичаїтись до світових тенденцій якомога раніше. В багатьох передових країнах мобільний Інтернет майже не поступається по популярності, а в деяких (наприклад, в Японії) навіть перевищує “стаціонарний”. Та й на Заході з появою <a href="http://www.apple.com/iphone/">iPhone</a>‘ів та в очікуванні виходу пристроїв з <a href="http://code.google.com/android/">Google Android</a> на борту, йде справжній бум мобільного Інтернету і, впевнений, що не так вже багато часу займе поки ці хвилі дійдуть і до нас.<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=7CfYvuB9hpw:iem8C0C9sfw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=7CfYvuB9hpw:iem8C0C9sfw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=7CfYvuB9hpw:iem8C0C9sfw:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/7CfYvuB9hpw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/111/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/111</feedburner:origLink></item>
		<item>
		<title>Правильне робоче середовище з xmonad</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/O8o4fymTB9Q/107</link>
		<comments>http://itblog.org.ua/post/107#comments</comments>
		<pubDate>Wed, 06 Aug 2008 07:32:20 +0000</pubDate>
		<dc:creator>Jolly Roger</dc:creator>
		
		<category><![CDATA[Софт]]></category>

		<category><![CDATA[desktop]]></category>

		<category><![CDATA[haskell]]></category>

		<category><![CDATA[xmonad]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/post/107</guid>
		<description><![CDATA[ Досить недавно в коментарях старого доброго опеннета (opennet.ru) розгорілась чергова війна KDE vs GNOME, в якій хтось ляпнув, що зручність - далеко не їх(вищевказаних монстрів) позитивна риса. Натомість коментатор запропонував звернути увагу на xmonad. Новий DE? Ні, ні і ще раз ні. Це фреймовий(або ж мозаїчний) менеджер вікон. Що ж, познайомимося з ним поближче.

Для [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://itblog.org.ua/wp-content/uploads/2008/08/xmonad.png" ilo-full-src="http://itblog.org.ua/wp-content/uploads/2008/08/xmonad.png" style="float: left" alt="xmonad" hspace="10" vspace="10" /> Досить недавно в <a href="http://www.opennet.ru/opennews/art.shtml?num=17027" title="Коментарі до новини">коментарях</a> старого доброго опеннета (<a href="http://opennet.ru" title="Портал відкритого ПЗ">opennet.ru</a>) розгорілась чергова війна KDE vs GNOME, в якій хтось ляпнув, що зручність - далеко не їх(вищевказаних монстрів) позитивна риса. Натомість коментатор запропонував звернути увагу на xmonad. Новий DE? Ні, ні і ще раз ні. Це фреймовий(або ж мозаїчний) менеджер вікон. Що ж, познайомимося з ним поближче.</p>
<p><span id="more-107"></span></p>
<p>Для більшості користувачів віконний менеджер починається і закінчується кількістю кнопочок в заголовку вікна. Ну, максимум -  з системного меню вікна. Далеко не кожен з нас задавався питанням: а що ж таке цей менеджер вікон? Судячи з назви,  він має керувати та організовувати зручну роботу в середовищі користувача. В типових віконних менеджерах маємо купу вікон, в багатьох випадках вікна перекривають одне одного, і бувають ситуації, коли знайти необхідне вікно виявляється дуже складно.  Через це еволюція віконних менеджерів породила віртуальні робочі столи. Так, це рішення ефктивне і зручне, але носить лиш суто екстенсивний хараткер. Так довго продовжуватись не могло.</p>
<p>Мозаїчні віконні менеджери підійшли до розв’язку задачі з іншого боку - змусити вікна не перетинати одне одного. Основний їх підхід - максимально збільшити ефективність використання простору робочого столу за рахунок поділу його на окремі частини &#8220;мозаїкою&#8221;. При цьому жоден піксель екрану не пропадає даремно, і всі вікна займають максимально можливий простір.</p>
<p>Для бажаючих лишитись зі своїм старим добрим робочим середовищем, будь то KDE, GNOME чи XFCE, і спробувати це диво софтобудівництва не змінюючи кардинально власних вподобань, існують відповідні <a href="http://haskell.org/haskellwiki/Xmonad" title="xmonad wiki">матеріали</a> .</p>
<p>Базові можливості xmonad можна почерпнути з відповідної сторінки manpage: <tt>man xmonad</tt>. Головне, чого я не знайшов там була відповідь на запитання: &#8220;А що ж то за клавіша така: mod?&#8221;, &#8212; на що вам зразу й дам відповідь: за замовчуванням модифікатором (все тим же mod-key) є клавіша Alt. До речі, всі операції можна виконувати за допомогою клавіатури, що значно підвищує швидкість роботи з вікнами, хоча миша також може маніпулювати розміщенням вікон.</p>
<p>Оскільки xmonad фактично не є десктоп середовищем, для підвищення ефективності роботи з ним додатково використовують окремі панелі <strong>dzen</strong> та <strong>xmodbar</strong> і динамічне X11 меню <strong>dmenu</strong> (яке, на жаль, не підтримує UTF-8, зате з задачами запуску чого-попало справляється на ура).</p>
<p>Якщо я ще не переконав читача спробувати xmonad, то цей невеличкий ролик неабияк може цьому посприяти:</p>
<p><center><object height="344" width="425"><param name="movie" value="about:blank"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/7ZAmMdRBRjs&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowfullscreen="true" height="344" width="425"></embed></object></center>Більше інформації можна знайти на сайті проекту: <a href="http://xmonad.org">http://xmonad.org</a>. А умільці програмувати на Haskell можуть ще й посприяти розробці <img src='http://itblog.org.ua/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=O8o4fymTB9Q:PPw5BQT_XMY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=O8o4fymTB9Q:PPw5BQT_XMY:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=O8o4fymTB9Q:PPw5BQT_XMY:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/O8o4fymTB9Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/107/feed</wfw:commentRss>
		<media:content url="http://feedproxy.google.com/~r/Itblog-ua/~5/qYqj3qM7enA/7ZAmMdRBRjs&amp;amp;hl=en&amp;amp;fs=1" fileSize="2655" type="application/x-shockwave-flash" /><feedburner:origLink>http://itblog.org.ua/post/107</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Itblog-ua/~5/qYqj3qM7enA/7ZAmMdRBRjs&amp;amp;hl=en&amp;amp;fs=1" length="2655" type="application/x-shockwave-flash" /><feedburner:origEnclosureLink>http://www.youtube.com/v/7ZAmMdRBRjs&amp;amp;hl=en&amp;amp;fs=1</feedburner:origEnclosureLink></item>
		<item>
		<title>Інтернет початку XXI сторіччя. Сервіси закладок та новин</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/6CrvQIM6LfM/110</link>
		<comments>http://itblog.org.ua/post/110#comments</comments>
		<pubDate>Tue, 05 Aug 2008 23:12:12 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
		
		<category><![CDATA[Блоги]]></category>

		<category><![CDATA[bookmarks]]></category>

		<category><![CDATA[del.icio.us]]></category>

		<category><![CDATA[digg]]></category>

		<category><![CDATA[web]]></category>

		<category><![CDATA[web 2.0]]></category>

		<category><![CDATA[соціальні мережі]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=343</guid>
		<description><![CDATA[Складно знайти в світі такого затятого інтернетчика, який не користувався б закладками. Але звичайні закладки в браузері - це вже сторіччя минуле. В сучасному ж Інтернеті популярні так звані сервіси &#8220;соціальних закладок&#8221;. Суть їх полягає в тому, що, по-перше, вони зберігаються не на машині користувача, а десь в Інтернеті, що доволяє синхронізувати їх між браузерами, [...]]]></description>
			<content:encoded><![CDATA[Складно знайти в світі такого затятого інтернетчика, який не користувався б закладками. Але звичайні закладки в браузері - це вже сторіччя минуле. В сучасному ж Інтернеті популярні так звані сервіси “соціальних закладок”. Суть їх полягає в тому, що, по-перше, вони зберігаються не на машині користувача, а десь в Інтернеті, що доволяє синхронізувати їх між браузерами, а це, погодьтесь, дуже зручно. По-друге, ці сервіси виконують певну статистичну функцію, підраховуючи кількість посилань на одну й ту саму адресу таким чином визначаючи їх популярність та ведучи їх рейтинг. Завдяки цьому одні користувачі сервісу можуть дізнаватись про посилання, які додали зробили інші. Існуючі наразі служби соціальних закладок можна поділити на дві умовні групи: орієнтовані на збереження посилань чи на поширення. Служби другого типу останнім часом називають вже соціальними новинами. Тобто новинами, рейтинг яких залежить від кількості людей, що за них проголосували.

І все-таки спочатку ми проговоримо про власне служби закладок. Типовими представниками яких є <a title="Delicious" href="http://delicious.com/">Delicious</a> та <a title="Opera Link" href="http://link.opera.com/">Opera Link</a>.
<h4>Соціальні закладки</h4>
<a title="Opera Link" href="http://link.opera.com/">Opera Link</a>. Цей сервіс - елемент порталу <a title="My Opera" href="http://my.opera.com">My Opera</a> і відповідно доступний лише користувачам веб-браузера <a title="Opera" href="http://http;//opera.com">Opera</a> починаючи з версії 9.5 і призначений суто для віддаленого збереження посилань, що дозволяє синхронізувати закладки між різними екземплярами браузера встановленими, наприклад, на домашньому та робочому комп’ютері. Хоча соціальним його назвати складно, адже створені вами закладки, на жаль (а може і на щастя) доступні лише вам.

<a title="Google Bookmarks" href="http://www.google.com/bookmarks/">Google Bookmarks</a>. Практично в усьому це аналог Лінку, але з підтримкою бразуерів  <a title="Firefox" href="http://www.mozilla.com/firefox/">Firefox</a> та Internet Explorer за допомогою <a title="Google Toolbar" href="http://http;//toolbar.google.com/">Google Toolbar</a>. І хоча я особисто цією службою не користувався, але знаю деяких людей, які це роблять. Ніби задоволені :)

<a href="http://www.scrnshots.com/users/graywolf/screenshots/42069"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/42069/delicious_med_rect.jpg" alt="" align="right" /></a>

<a title="Delicious" href="http://delicious.com/">Delicious</a> (колись відомий як <a title="del.icio.us" href="http://del.icio.us/">del.icio.us</a>). От це вже цікавіше. Як і Гугл Букмаркс, Делішес повністю інтегрується із закладками в браузерах <a title="Firefox" href="http://www.mozilla.com/firefox/">Firefox</a> та Internet Explorer за допомогою відповідних плагінів (наприклад, для Вогнелиса його можна знайти <a title="тут" href="http://delicious.com/help/quicktour/firefox">тут</a>). Але на відміну від двох попередніх закладки відкриті (тобто їх можуть продивитись інші), плюс він дозволяє ставити на закладки мітки (теги), що набагато гнучкіше традиційного ієрархічного підходу до сортування та підраховує кількість посилань на одну й ту саму адресу від різних користувачів. Найбільш популярні посилання з’являються на головній сторінці.

Ну, здається, і все. Точніше інші сервіси такого типу (наприклад, російський <a title="БобрДобр" href="http://bobrdobr.ru">БобрДобр</a>), але просто вони набагато менш відомі.
<h4>Соціальні новини</h4>
З другою групою цікавіше, бо це зараз чи не останній писк і там панує затята конкурентна боротьба. Головною її відмінністю є те, що посилання публікуються не стільки для себе, скільки для того, щоб надати цікаву інформацію іншим. Тобто як це все працює: будь-який користувач має право додати лінку на якийсь сайт чи конкретну новину, забезпечивши її коротким описом. Це посилання попадає в загальну стрічку новин і якщо воно зацікавило когось з активних користувачів, то він може перейти на сайт з повною новиною, прокоментувати її та проголосувати за неї. Новини з найбільшою кількістю голосів (насправді там все дещо складніше, але…) потрапляють відповідно в топ новин (тобто найцікавіші для значної кількості активних користувачів). Звісно, не все так безхмарно. Зараз сайти соціальних новини масово критикують з двох основних причин: по-перше, неможливість проконтролювати їх достовірність (якась цікава, але недостовірна інформація може легко вийти в топ завдяки людському фактору), а по-друге, теоретична можливість накрутки голосів із-за чого розробникам цих сайтів постійно доводиться вдосконалювати механізми відбору топових новин. Ну а тепер згадаємо і самих представників:

<a href="http://www.scrnshots.com/users/graywolf/screenshots/42097"><img src="http://s3.amazonaws.com/scrnshots.com/screenshots/42097/digg_med_rect.jpg" alt="" align="right" /></a>

<a title="Digg" href="http://digg.com/">Digg</a>. З цього стартапу, мабуть, і почався бум сайтів соціальних новин. Дігг - це взірець всього описаного вище: як переваг так і недоліків. Його назва навіть увіковічена в новому терміні під назвою “digg-ефект” - це короткочасне, але дуже значне підвищення відвідуваність сайту на який посилається новина, щопопала в топ новин на Digg. Дуже часто цей ефект - справжнє випробування для хостингу, бо кількість відвідувачів може збільшитись не на один порядок.

<em>Note:</em> як мене вже виправили, насправді вперше це поняття з’явилось як <a href="http://en.wikipedia.org/wiki/Slashdot_effect">slashdot-ефект</a> і характеризувало інший сайт новин - <a href="http://slashdot.com/">Slashdot</a>, про який я в цьому дописі не згадую. Він в певному сенсі аналогічний описуваним, але не має вираженої соціальної складової, оскільки лінки на новини, які попадають в топ відбирає спеціальний склад редакторів слешдоту, а не самі користувачі.

<a title="Yahoo! Buzz" href="http://buzz.yahoo.com/">Yahoo! Buzz</a>. Лаври  <a title="Digg" href="http://digg.com/">Digg</a> багатьом не давали спокою, в тому числі і компанії <a title="Yahoo!" href="http://yahoo.com/">Yahoo!</a>, яка вирішила не відставати і випустити свій аналог. Тим паче, що в них було чим звабити користувачів: новини, які попадають в топ Базза потрапляють і в новини на основній сторінці порталу <a title="Yahoo!" href="http://yahoo.com/">Yahoo!</a>. А це не багато, не мало найпопулярніший в Інтернеті сайт.

<a title="StumbleUpon" href="http://stumbleupon.com/">StumbleUpon</a>. Ще один Digg-клон, але з цікавою родзинкою, яка полягає в можливості помічати не лише лінки, а й окремі картинки, або відео з сайтів типу <a title="YouTube" href="http://youtube.com/">YouTube</a>.

Серед інших відомих варто згадати <a title="Reddit" href="http://reddit.com/">Reddit</a>, <a title="Mixx" href="http://mixx.com/">Mixx</a>, <a title="Furl" href="http://www.furl.net/">Furl</a> та ще декілька, але я ними ще не користувався, тому сказати щось гарне чи погане не можу…

Якщо говорити про щось більш приземлене до наших реалій, тобто сайти з україно- та російськомовними новинами, то про перші можна <a title="прочитати тут" href="http://fireon.org.ua/ukraine/ukrainian-digg.html">прочитати тут</a>, а серед других єдиний відомий мені, але очевидний лідер - <a title="news2.ru" href="http://news2.ru/">news2.ru</a>. Щоправда основна їх біда - це мала відвідуваність. Особливо це стосується україномовних аналогів, де важко знайти “популярні” новини з більш ніж 5 голосами в той час як для буржуйських рахунок йде на сотні, а для російських хоча б на десятки.

Ну от ніби і все. Гарних вам новин ;)<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=6CrvQIM6LfM:S9kNDmYGEig:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=6CrvQIM6LfM:S9kNDmYGEig:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=6CrvQIM6LfM:S9kNDmYGEig:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/6CrvQIM6LfM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/110/feed</wfw:commentRss>
		<media:content url="http://feedproxy.google.com/~r/Itblog-ua/~5/lXUKjA9Wv3o/" type="application/xml" /><feedburner:origLink>http://itblog.org.ua/post/110</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Itblog-ua/~5/lXUKjA9Wv3o/" length="-1" type="application/xml" /><feedburner:origEnclosureLink>http://link.opera.com/</feedburner:origEnclosureLink></item>
		<item>
		<title>Disqus</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/L0UMAgq2SjQ/106</link>
		<comments>http://itblog.org.ua/post/106#comments</comments>
		<pubDate>Sun, 29 Jun 2008 11:19:20 +0000</pubDate>
		<dc:creator>minus-one</dc:creator>
		
		<category><![CDATA[Блоги]]></category>

		<category><![CDATA[blogging]]></category>

		<category><![CDATA[disqus]]></category>

		<category><![CDATA[web]]></category>

		<category><![CDATA[web 2.0]]></category>

		<guid isPermaLink="false">http://kilesa.org.ua/?p=231</guid>
		<description><![CDATA[Disqus (діскас) — крута онлайн-система коментарів. Недавно про них почув, трохи потикав і одразу захопився. Переваг дуже багато. Але багато і різних контроверсійних моментів&#8230; 
Централізація і деблогізація коментарів
Довгий час багато хто вважав коментарі якимось ледь не &#8220;довіском&#8221; до постів на блозі — важливим, корисним, але довіском. Стандартні вордпрес-коментарі представляють собою плоску послідовність відповідей-реакцій на пост. [...]]]></description>
			<content:encoded><![CDATA[<a href="http://disqus.com/"><strong>Disqus</strong> (діскас)</a> — крута онлайн-система коментарів. Недавно про них почув, трохи потикав і одразу захопився. Переваг дуже багато. Але багато і різних контроверсійних моментів…
<h1>Централізація і деблогізація коментарів</h1>
Довгий час багато хто вважав коментарі якимось ледь не “довіском” до постів на блозі — важливим, корисним, але довіском. Стандартні вордпрес-коментарі представляють собою плоску послідовність відповідей-реакцій на пост. Нема можливості відповісти на якийсь цікавий вам коментар. Нема можливості “проголосувати” за нього. Неясно, що за людина автор коментаря. Не вибудовується дискусії, коротше…

Адже коментарі і самі “генерять контент” (так би мовити), і самі можуть бути предметом коментарів. І саме так будується звичайна розмова — вона постійно відгалужується; і той, хто її розпочав не обов’язково має більше ваги. Останнім часом все більше людей починають розуміти, що коментарі — це повноцінні дискусії, які можуть досить таки далеко відходити від теми, що їх спровокувала; в яких можуть бути відгалуження і діалоги; які, коротше кажучи, повинні мати <strong>більше форумних фіч</strong>. Так само і коментатори — їх треба цінувати, їм треба полегшувати життя, з ними треба розмовляти і за ними цікаво спостерігати на інших блогах. Вони мають право редагувати чи знищити свій коментар, або, напр., мати його копію у незалежному місці (на випадок, якщо це дуже важливий коментар, а блог, де він був опублікований, вже не існує…) і т.д… <a href="http://blog.disqus.net/2008/05/30/a-commenters-rights/">подальше читання на тему “які мають бути права коментаторів” тут</a> (читайте не тільки сам пост, але і коментарі до нього <img alt=";-)" src="http://kilesa.org.ua/wp-includes/images/smilies/icon_wink.gif" /> ) ).

Пропозицією саме на цей попит стали декілька систем онлайн-коментарів, покликаних “відв’язати” коментарі від конкретних блогів і, взагалі, створити єдине централізоване місце для дискусій (а блоги і пости мають лише надавати їм контекст): <em><a href="http://intensedebate.com/">Intense Debate</a></em>, <em><a href="http://www.sezwho.com/">SezWho</a></em>, <a href="http://disqus.com/"><strong>Disqus</strong></a>…
<h1>Плюси</h1>
<em>Діскас</em> подобається одразу. Ви реєструєтесь, отримуєте плагін для вордпресу (чи чого іншого), встановлюєте його собі на блог (<a href="http://disqus.com/custom-css/"><strong>трохи твікаєте css</strong></a>, якщо потрібно) — і все! Замість стандартних вордпресівських коментарів у вас інтегрована ціла онлайн-система, яка надає, зокрема, такі можливості:
<ol>
	<li>Розгалужені (threaded) коментарі — можливість відповідати на чийсь коментар, не тільки на основний пост</li>
	<li>Відео-коментарі(!) — можливість залишати у відповідь своє відео, яке можна записати прямо тут же по місцю (вам знадобиться <strong><a href="http://www.seesmic.com/">seesmic</a></strong>-акаунт)</li>
	<li>Єдині профілі — наскрізна ідентифікація, де б ви що не постили (з можливістю <em>заявити права</em> (claim) на свої старі коментарі, які ви постили, ще не зареєструвавшись на disqus!)</li>
	<li>Система рейтингів коментарів і юзерів (і можливість відповідно відсортувати гілку) — безглузді коментарі швидко опиняються “внизу”</li>
	<li>Можливість навівши мишу на аватар коментатора побачити його останні коментарі (і не тільки на вашому блозі — по всьому вебу(!) (і можливість підписатися на ці його коментарі <img alt=";-)" src="http://kilesa.org.ua/wp-includes/images/smilies/icon_wink.gif" /> ))</li>
	<li>Форум на сервері disqus, що дублює усю дискусію — коментарі можна лишати і там і тут, вони будуть відображені скрізь</li>
	<li>Інтеграцію у френдфід: де б ви що не коментували — усе буде проходити у вашому потоці</li>
	<li>Підтримка <strong>OpenID</strong>, <strong><a href="http://en.gravatar.com/">граватарів</a></strong> (увага! тільки при реєстрації з сайту — по місцю коментування поки що не працює! (треба спочатку піти на сайт)) і трекбеків…</li>
</ol>
Коротше, усіх переваг і не перелічити… (<a href="http://blog.disqus.net/2008/05/14/disqus-now-with-100-more-video/">краще раз подивитися</a>… <img alt=";-)" src="http://kilesa.org.ua/wp-includes/images/smilies/icon_wink.gif" /> ) Коментарі стають справжніми розмовами і велика частина уваги переходить з власне посту на них.
<h1>Контроверсійні моменти</h1>
АЛЕ. Є і свої “але”; і головне з них — <strong>коментарі перестають бути частиною блога</strong>(!) Вони навіть зберігаються “на стороні”. І це означає багато в чому втрату контролю над ними. Ні, модерацію ви зможете здійснювати, з цим все ок — просто що буде, якщо disqus накриється мідним тазиком? Де будуть ваші коментарі? (такі цінні вашому серцю?) <em>Діскас</em> має можливість <strong>експорту коментарів у xml</strong>. Та <strong>немає (поки) можливості імпорту цього xml назад у вордпрес</strong>! (на випадок, якщо ви схочете повернутися на вордпресівський варіант, мало що в житті буває…)

Взагалі, попереджаю: інтеграція вордпресівських коментарів у діскас поки що не реалізована зовсім! При установці вам буде запропоновано три варіанти поведінки:
<ol>
	<li>замінити вордпресівські коментарі на всіх постах — <em>обережно! старі коментарі не будуть більше відображатися!</em></li>
	<li>замінити усі пости без коментарів (включно з майбутніми) — <em>я зробив би саме так</em></li>
	<li>замінити коментарі тільки на постах, закритих для коментування — <em>(нафіга?)</em></li>
</ol>
Найкращий варіант — другий; так всі старі коментарі залишаться у вордпресівському варіанті (і він працюватиме з ними і надалі), а нові стануть disqus. У першому же випадку старі коментарі “пропадуть” (але не з бази даних, не хвилюйтесь — коли з’явиться імпорт, їх можна буде залучити у disqus), і ви почнете з нуля (тому будьте уважні, цього небагато хто хоче…)

Щодо відео-коментування теж питання: дехто вважає (і небезпідставно), що <strong>вони порушують загальну зв’язність коментарів</strong> — коли люди дивляться на текстові коментарі вони мають змогу швидко “пробігти” текст очима, виділити цікаві для себе моменти і вже на них зосередитися; коли ж серед тексту зустрічається відео — його очима не пробіжиш! — прийдеться дивитися… (а це може бути щось типу “ну от, це мій перший відео-коментар…” — не обов’язково всім цікава річ, не?..) Але з іншого боку, у відео є і свої плюси: якщо ви хочете похизуватись своєю новою мобілкою, напр., чи спитати якого кольору кросівки вам більш пасують — краще варіанту і не придумаєш!

Є у disqus й ще декілька мінусів, що стосуються в основному дизайну — загалом-то він працює скрізь, але дрібні недоробки присутні. Напр., в іе вікно log in (по місцю коментування) криве, а в опері — не дозволяє ввести пароль (приходиться іти на сайт і робити це там). Є помилки в реалізації вордпрес-функції disqus_recent_comments() (що показує останні коментарі) — в одному місці вони забули закрити тег <code>&lt;/em&gt;</code>, і через це вся сторінка лізе наперекосяк (зробіть пошук у файлі disqus.php по слову ago і одразу після нього додайте <code>&lt;/em&gt;</code>, щоб пофіксити це (та сподіваюсь, вони скоро пофіксять це і самі)).

Головне ж це те, що <strong>все реалізовано як яваскрипт — тому пошуковики НЕ ІНДЕКСУЮТЬ коментарі на вашому блозі</strong>! (плюс страждає швидкість завантаження сторінки трохи…) У них є варіант <strong>API-плагіна для вордпреса</strong> — але
<blockquote>This version is out of date. We recommend using 1.04 until a new version of the API plugin is released</blockquote>
— тобто його версія наразі застаріла (багато фіч не підтримується). АПІ-плагін генерує html, а він індексується пошуковиками — тому цей варіант був би ідеальним. На жаль, поки що він в повній мірі недоступний <img alt="-(" src="http://kilesa.org.ua/wp-includes/images/smilies/icon_sad.gif" /> …

І наостанок, для тих, хто вирішить спробувати disqus у себе локально: <a href="http://disqus.com/help/"><strong>почитайте уважно FAQ</strong></a>! — особливо в плані <a href="http://disqus.com/help/#faq-14">Can I test on a local or private server?</a>:
<blockquote>Yes. Set the following JavaScript parameter.
var disqus_container_id = “your-custom-id”;</blockquote>
— тільки додам, що зробити це треба <em>у файлі comments.php у перших тегах “script”</em>.

До речі, на <a href="http://tumblr.com/"><em>Тумблері</em></a> disqus давно єдина система коментарів, <a href="http://minus-one.tumblr.com/">і я собі там його поставив теж</a> — так що завжди можна потикати <img alt=";-)" src="http://kilesa.org.ua/wp-includes/images/smilies/icon_wink.gif" /> .

<u>Bottom-line</u>: disqus ще зовсім молодий стартап, і багато що їм треба ще доробити. Але ті фічі, що вже є, — досить-таки вражають. (Звісно, усе це можна реалізувати за допомогою плагінів (і зробити навіть краще) — але скільки плагінів вам для цього знадобиться?.. <img alt=";-)" src="http://kilesa.org.ua/wp-includes/images/smilies/icon_wink.gif" /> і як все це обслуговувати?..) У мене локально вже все готово для переходу на <em>діскас</em>: щойно вони нададуть можливість зворотнього імпорту їхніх коментарів назад у вордпресівський формат — я їхня людина без питань! ^__^ (зі всім іншим можна жити…)<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=L0UMAgq2SjQ:zb6EdGRVbtg:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=L0UMAgq2SjQ:zb6EdGRVbtg:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=L0UMAgq2SjQ:zb6EdGRVbtg:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/L0UMAgq2SjQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/106/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/106</feedburner:origLink></item>
		<item>
		<title>FriendFeed Share Bookmarklet для Опери</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/3ua3BafpiwE/105</link>
		<comments>http://itblog.org.ua/post/105#comments</comments>
		<pubDate>Tue, 17 Jun 2008 15:15:22 +0000</pubDate>
		<dc:creator>minus-one</dc:creator>
		
		<category><![CDATA[Блоги]]></category>

		<category><![CDATA[friendfeed]]></category>

		<category><![CDATA[opera]]></category>

		<guid isPermaLink="false">http://kilesa.org.ua/?p=229</guid>
		<description><![CDATA[На френдфіді є така кльова закладочка — Share Bookmarklet. За її допомогою можна розшарювати на фф з будь-якої сторінки різну інфу. Зокрема вона прикольно працює із фотками — клікаєш фотки на сторінці, які сподобалися, і вони додаються у фрейм закладки, а потім і на фф (як мініатюра) (див. приклад). 
Усе б нічого, та з Оперою [...]]]></description>
			<content:encoded><![CDATA[На <a href="http://friendfeed.com">френдфіді</a> є така кльова закладочка — <strong><a href="http://friendfeed.com/share/bookmarklet">Share Bookmarklet</a></strong>. За її допомогою можна розшарювати на фф з будь-якої сторінки різну інфу. Зокрема вона прикольно працює із фотками — клікаєш фотки на сторінці, які сподобалися, і вони додаються у фрейм закладки, а потім і на фф (як мініатюра) (<a href="http://friendfeed.com/e/32f79782-3bce-11dd-97f7-003048343a40/Himitsu-Top-Secret-MyAnimeList-net/">див. приклад</a>).

Усе б нічого, та з <strong>Оперою</strong> це не працює! (тобто так все нормально, а з картинками ну ніяк…) І це так прикро — простий яваскрипт не могли вже з усім сумісний написати… Ну я собі подивився, що за помилку пише Опера — “attempted to write protected variable”. Тоді зайшов подивитись на код, який цю помилку генерує. І з’ясувалось, що вся проблема в тому, що скрипт оперує адресами (чи що) з різними протоколами: https і http — а Опера (логічно) сприймає їх як різні об’єкти і не дозволяє обмінюватися даними між ними (щось таке коротше). А інші браузери на це плювали. <a href="http://friendfeed.com/share/bookmarklet/javascript">В усьому оригінальному скрипті</a> це https зустрічається один раз, в інших місцях завжди http. Одним словом, склалося у мене враження, що хтось просто помилився з цим https. Тому я написав свій <strong><a href="http://kilesa.org.ua/ff-bookmarklet-fix.js">користувацький яваскрипт</a></strong> (є в Опері така корисна штука), який <strong>просто заміняє цей https на http</strong> — і все запрацювало!

Взагалі-то я написав розробникам фф про це, але поки відповіді немає — кому треба, може корисуватися <img alt=";-)" src="http://kilesa.org.ua/wp-includes/images/smilies/icon_wink.gif" /> (як бачите, це диво програмістського мистецтва кожного разу, коли запускається закладка, тупо робить пошук-заміну https на http в їхньому скрипті (хто вміє, хай напише краще)).

Коротше, мораль: Опера як завжди ні в чому не винна… Вони лише чітко дотримуються стандартів (і що інші на ці стандарти забивають — то вже не їх проблема). У даному випадку, скоріше за все, має місце просто програмістський ляп; та якби проблема спливла б не в Опері — як швидко його б виправили! А так, тяганина…<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=3ua3BafpiwE:zO-9XjG8Xd8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=3ua3BafpiwE:zO-9XjG8Xd8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=3ua3BafpiwE:zO-9XjG8Xd8:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/3ua3BafpiwE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/105/feed</wfw:commentRss>
		<media:content url="http://feedproxy.google.com/~r/Itblog-ua/~5/sExQr5uSsEs/ff-bookmarklet-fix.js" fileSize="296" type="application/javascript" /><feedburner:origLink>http://itblog.org.ua/post/105</feedburner:origLink><enclosure url="http://feedproxy.google.com/~r/Itblog-ua/~5/sExQr5uSsEs/ff-bookmarklet-fix.js" length="296" type="application/javascript" /><feedburner:origEnclosureLink>http://kilesa.org.ua/ff-bookmarklet-fix.js</feedburner:origEnclosureLink></item>
		<item>
		<title>Тепер і Яndex тебе знайде!</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/Fdc-FqSYVHQ/104</link>
		<comments>http://itblog.org.ua/post/104#comments</comments>
		<pubDate>Sun, 15 Jun 2008 10:50:56 +0000</pubDate>
		<dc:creator>FerR0zer</dc:creator>
		
		<category><![CDATA[Мережі та телекомунікації]]></category>

		<category><![CDATA[google]]></category>

		<category><![CDATA[google maps]]></category>

		<category><![CDATA[yandex]]></category>

		<category><![CDATA[мобільний]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/post/104</guid>
		<description><![CDATA[&#8230; Щоправда,  тільки якщо ти поставиш собі на мобільний чи смартфон нову версію мобільної Яндекс.Карти.
Раніше я вже писав про подібний функціонал в мобільній версії GoogleMaps. Правда, з картою Києва там поки що напряг - тільки супутникові знімки та карта основних автошляхів України.
Оновив недавно на смарті  Яндекс.Карту, а вона після завантаження першим ділом показала моє місцезнаходження. [...]]]></description>
			<content:encoded><![CDATA[<p><img SRC="http://img.yandex.net/i/logo76x33.gif" BORDER="0" WIDTH="76" HEIGHT="33" ALIGN="left" />&#8230; Щоправда,  тільки якщо ти поставиш собі на мобільний чи смартфон нову версію мобільної <a HREF="http://mobile.yandex.ru/maps/">Яндекс.Карти</a>.</p>
<p>Раніше я <a TITLE="Гугля тебе знайде…" HREF="http://itblog.org.ua/post/20">вже писав</a> про подібний функціонал в мобільній версії GoogleMaps. Правда, з картою Києва там поки що напряг - тільки супутникові знімки та карта основних автошляхів України.</p>
<p>Оновив недавно на смарті  Яндекс.Карту, а вона після завантаження першим ділом показала моє місцезнаходження. Загалом тестував в мережах Київстару, МТС та Білайну - працює коректно, точність визначення місцезнаходження в Києві - залежно від місця та мережі 100-5000 метрів. В Білайновській мережі в деяких місцях показує точніше, ніж гугловська (там, мабуть, база &#8220;зсунута&#8221; на одну вишку використовується - показує сусідню соту).</p>
<p>Фукцією Пробки 2.0 активно не користувався, але в цілому ідея сподобалась - при наявності модуля GPS та ввімкненому режимі &#8220;Сообщать о пробках&#8221; (параноїки, увага! режим за замовчанням ввімкнений :)) дані про місцезнаходження та швидкість пересування автоматично передається на сервер Яндексу, де інформація від багатьох &#8220;волонтерів&#8221; збирається та наноситься на карту. Можна також вручну ввести дані про пробку.</p>
<p>З українських доступні карти Києва, Дніпропетровська, Донецька, Запоріжжя, Львову, Одесси, Харкова та  Криму.</p>
<p><img SRC="http://mobile.yandex.ru/i/ymm-m.png" BORDER="0" WIDTH="84" HEIGHT="84" ALIGN="right" /></p>
<p>Щоб і собі отримати таке чудо на телефон,  перейдіть з мобільного за адресою m.ya.ru/ymm або по бар-коду справа. Модель телефону в більшості випадків визначається автоматично.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=Fdc-FqSYVHQ:K2YZSjRp0zk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=Fdc-FqSYVHQ:K2YZSjRp0zk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=Fdc-FqSYVHQ:K2YZSjRp0zk:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/Fdc-FqSYVHQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/104/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/104</feedburner:origLink></item>
		<item>
		<title>Ви все ще використовуєте bash? Тоді ми до вас!</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/iL1rLvgqfps/102</link>
		<comments>http://itblog.org.ua/post/102#comments</comments>
		<pubDate>Tue, 03 Jun 2008 21:48:07 +0000</pubDate>
		<dc:creator>Jolly Roger</dc:creator>
		
		<category><![CDATA[Howto]]></category>

		<category><![CDATA[Софт]]></category>

		<category><![CDATA[linux]]></category>

		<category><![CDATA[unix]]></category>

		<category><![CDATA[zsh]]></category>

		<category><![CDATA[консоль]]></category>

		<guid isPermaLink="false">http://itblog.org.ua/post/102</guid>
		<description><![CDATA[Вже давним-давно хотів зрозуміти причину страшенних війн стосовно командної оболонки (shell). З Bash я був знайомий з самого початку мого використання Linux, але майже ніхто його не хвалив. Так, всі казали, що це дефолтний, громіздкий командний інткрпретатор, додаючи ще купу епітетів явно не на його користь. І ось одного разу я таки вирішив спробувати щось [...]]]></description>
			<content:encoded><![CDATA[<p>Вже давним-давно хотів зрозуміти причину страшенних війн стосовно командної оболонки (shell). З Bash я був знайомий з самого початку мого використання Linux, але майже ніхто його не хвалив. Так, всі казали, що це дефолтний, громіздкий командний інткрпретатор, додаючи ще купу епітетів явно не на його користь. І ось одного разу я таки вирішив спробувати щось інше.</p>
<p>Коли новенький ZSH стартував як мій дефолтний шелл, я ще дуже довго не міг зрозуміти, чим же він настільки хороший. Це якраз той варіант, коли баш виглядав краще, оскільки був дефолтним і мав вже деякі настройки хоча б того ж запиту на ввід ($PROMPT, $PS[1-4]), а тут споглядання картини</p>
<p><code>localhost%</code></p>
<p>ніяк не радувало. Так моє перше знайомство і закінчилося б, якби мені не було ліньки поставити баш назад (думка &#8220;дай ще потестю, мож ще що цікаве вилізе&#8221; промайнула у мене в мізках і вирішила хід подій). З часом я звик до цього шелла, його невеликих особливостей, і нарешті почав бачити різницю в швидкості роботи (порівнюючи роботу bash і zsh на різних користувачах).</p>
<p>А поки час ішов, я ще не раз бачив деякі &#8220;розфарбовані&#8221; екземпляри все того ж ZSH, і мені кортіло нарешті й собі таку цяцьку. І ось нарешті моя мрія здійснилась, і я з вами всім цим щастям поділюсь <img src='http://itblog.org.ua/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p><span id="more-102"></span></p>
<p>А почнемо ми знову ж з запиту на ввід. Купа мануалів та записів в блогах пропонує його в наступному вигляді:</p>
<p><code>[user@hostname:directory]#</code></p>
<p>На додачу до цього, ми ще й годинник прикрутимо справа;) Відкриваємо ~/.zshrc і вписуємо наступне:</p>
<p><code><br />
export PROMPT='[%n@%m:%1~]%# &#8216;<br />
export RPROMPT=&#8217;[%*]&#8216;<br />
alias ls=&#8217;ls &#8211;color&#8217;<br />
alias grep=&#8217;grep &#8211;color&#8217;<br />
</code></p>
<p>Тут перший рядок відповідає за відображення запиту на ввід(в даному випадку дуже схожий на типовий в RedHat Linux), другий - за годинник, все інше знайомо до болю ще з часів bash-а. Ну а тепер можна цей самий запит і розфарбувати. Після додавання інформації про колір, частина нашого .zshrc виглядає наступним чином:</p>
<p><code><br />
alias ls='ls --color'<br />
alias grep='grep --color'<br />
autoload colors<br />
colors<br />
PROMPT="[%{${fg[green]}%}%n%{${reset_color}%}@%{${fg[blue]}%}%m%{${reset_color}%}:%{${fg[red]}%}%1~%{${reset_color}%}]%# &#8221;<br />
RPROMPT=&#8221;[%{${fg[cyan]}%}%*%{${reset_color}%}]&#8221;<br />
fpath=(~/myfns $fpath)<br />
autoload -U promptinit<br />
promptinit<br />
</code></p>
<p>Думаю, і так все зрозуміло написано навіть без коментарів. Результат наших з вами налаштувань виглядатиме десь так:</p>
<p><center><img src="http://itblog.org.ua/wp-content/uploads/2008/06/zsh.png" ilo-full-src="http://itblog.org.ua/wp-content/uploads/2008/06/zsh.png" alt="ZSH coloured prompt" /></center>Зазначу, що в принципі отримати екзотичний вигляд шелла можна і без роботи напильником: в системі вже є невеличкий підбір оформлення, список можна отримати командою<code> prompt -l </code>, ну а встановити один з них можна, наприклад, так:</p>
<p><code>prompt elite</code></p>
<p>І на додачу вам кілька посилань на ресурси, присвячені цьому шеллу:<br />
<a href="http://wiki.archlinux.org/index.php/Zsh" title="ZSH Wiki Page for ArchLinux" target="_blank"> http://wiki.archlinux.org/index.php/Zsh</a><br />
<a href="http://rayninfo.co.uk/tips/zshtips.html" title="ZSH Tips" target="_blank"> http://rayninfo.co.uk/tips/zshtips.html</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=iL1rLvgqfps:nEVwFhRLIeY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=iL1rLvgqfps:nEVwFhRLIeY:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=iL1rLvgqfps:nEVwFhRLIeY:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/iL1rLvgqfps" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/102/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/102</feedburner:origLink></item>
		<item>
		<title>Wordpress: додаємо RSS у FeedBurner</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/zCWo4IY829s/100</link>
		<comments>http://itblog.org.ua/post/100#comments</comments>
		<pubDate>Fri, 09 May 2008 22:02:47 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
		
		<category><![CDATA[Блоги]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=324</guid>
		<description><![CDATA[Захотілося мені нещодавно додати свою RSS-ку з блогу у Feedburner для статистики. Здавалося б: немає нічого простиіше, адже для цього у Вордпреса є навіть спеціальний плагін. Та насправді не все йде по маслу, якщо ви використовуєте фільтрацію по тегам чи категоріям (tag/category filtering), а плагін редіректить будь-який фід: повний він чи фільтрований на повний фід [...]]]></description>
			<content:encoded><![CDATA[<p>Захотілося мені нещодавно додати свою <a href="http://graywolf.org.ua/feed/">RSS</a>-ку з блогу у <a href="http://feedburner.com/">Feedburner</a> для статистики. Здавалося б: немає нічого простиіше, адже для цього у Вордпреса є навіть <a href="http://www.google.com/support/feedburner/bin/topic.py?topic=13252">спеціальний плагін</a>. Та насправді не все йде по маслу, якщо ви використовуєте фільтрацію по тегам чи категоріям (tag/category filtering), а плагін редіректить будь-який фід: повний він чи фільтрований на повний фід у Фідбьорнері. Ясно було, що потрібно якось їх розмежовувати, наприклад, за допомогою файлу <em>.htaccess</em>.  Покопавшись трохи в інеті знайшов-таки симпатичне рішення:</p>
<textarea name="code" cols="60" rows="10">
 RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(feed|wp-atom|wp-feed|wp-rss|wp-rdf)(.+)\ HTTP/ [NC,OR]
 RewriteCond %{QUERY_STRING} ^feed [NC]
 RewriteCond %{HTTP_USER_AGENT} !^(FeedBurner|FeedValidator) [NC]
 RewriteRule .* http://feeds.feedburner.com/адреса_фіду_на_feedburner [R=307,L]
</textarea>
<p>P.S. До речі, зверніть увагу на рядок з фільрацією по User-Agent. Його не варто видаляти - пересвідчився на власному досвіді - я першим ділом його &#8220;прооптимізував&#8221;. Але без нього Feedburner при опитванні фіду з вашого сайту редіректиться сам на себе, а не читає оригінал і виходить, звісно, дурня.
<div>
</div>
</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=zCWo4IY829s:Ur3jG6n6eIo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=zCWo4IY829s:Ur3jG6n6eIo:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=zCWo4IY829s:Ur3jG6n6eIo:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/zCWo4IY829s" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/100/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/100</feedburner:origLink></item>
		<item>
		<title>Hibernate + External HDD + неуважність = великі неприємності</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/xH1QGcMb7Oc/98</link>
		<comments>http://itblog.org.ua/post/98#comments</comments>
		<pubDate>Fri, 02 May 2008 18:14:36 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
		
		<category><![CDATA[Блоги]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=315</guid>
		<description><![CDATA[Ще на минулому тижні сталася в мене невеличка як мені тоді здалося халепа&#8230; Збирався, значить, я на роботу, а ноут я зазвичай не виключаю, а hibernate&#8217;чу, бо мені лінька чекати поки він завантажиться&#8230; Ну от вимкнув я його, витягнув USB-шнурки від двох своїх зовнішніх HDD, поклав ноута в рюкзак і почалапав на роботу. Там часу [...]]]></description>
			<content:encoded><![CDATA[<p>Ще на минулому тижні сталася в мене невеличка як мені тоді здалося халепа&#8230; Збирався, значить, я на роботу, а ноут я зазвичай не виключаю, а hibernate&#8217;чу, бо мені лінька чекати поки він завантажиться&#8230; Ну от вимкнув я його, витягнув USB-шнурки від двох своїх зовнішніх HDD, поклав ноута в рюкзак і почалапав на роботу. Там часу діставати його не було, тож він так і пролежав у мене в сумці цілий день. Коли ж приперся знову додому, то спочатку знову підключив HDD і потім включив ноута ще не знаючи, що я тільки-но підписав смертельний вирок купі файлів. А справа в чому&#8230; Коли комп хібернейтиться, то він робить паузу в роботі і скидає поточний вміст оперативної пам&#8217;яті на жорсткий диск. Коли ж &#8220;прокидається&#8221;, то відновлює стан ОП та починає роботу з того місця, на якому спинився. І от тут-то і закралася фігня. Зазвичай я стараюсь робити для зовнішніх вінтів &#8220;Безопасное извлечение&#8221; перед тим як хібернейтити, але нерідко, коли дуже поспішаю, забуваю. Потім, коли вмикаю його на роботі, він одразу матюкається, що не може щось там своє службове записати на неіснуючий вже диск і заспокоюєтсья. Ну так от, коли я повернувся, то звсунув USB-роз&#8217;єми від вінтів навхрест (взагалі я втикав їх завжди куди прийдеться не дивлячись який вінт в який USB-порт я підключаю) і вийло так, що вінди вирішили, що все так і треба і спробували віддати команди вінтам на запис, але оскільки структура файлів та каталогів там відрізняється, то це зіпсувало інформацію у таблиці файлів NTFS. В результаті чого дисковий розділ на одному з HDD геть перестав розпізнаватись, а на другому HDD з першого розділу зникла вся інформація. Для другого я запусти віндовий scandisk (хоч і чуяло моє серце, що роблю я дурницю), для друого це не допомагало, бо його ФС взагалі не роспізнавалась як NTFS, тому довелось терміново в неті шукати софт для відновлення. Поки укав софт, scandisk типу як відновив один з розділів (на ньому, до речі зберігались фотки). Поверхово оглянувши результати його роботи я заспокоївся, бо ніби все повернулось, хоч і внутрішній голос підказував, що кількість папок з фотографіями значно зменшилась. Я забив на той внутрішній голос, бо проблема з повністю мертвим розділом здавалась більш нагальною. Не вдаючись в детеалі скажу, що інфу завдяки R-Studio вдалося відновити. Але повернемося до диску з фотками&#8230; Я ж думав, що все ОК і вже встигнув скинути туди купу нових фоток зроблених за вихідні, аж тут мені знадобились минулорічні фотки зі Львова. Кинувся шукати - на вінту нема, в минулорічних бекапах на DVD теж нема і тут до мене доходить, що scandisk мені зробив ведмежу послугу. Запсускаю R-Studio знову&#8230; Виявилось, що він мені не відновив як мінімум половину з фоток, що були. Р-Студіо відновило папки, але дані в багатьох з них вже були пошматовані <img src='http://graywolf.org.ua/wp-includes/images/smilies/icon_sad.gif' alt='(' /> В одих папках пошкоджені були 2-3 файли, в інших - десятки <img src='http://graywolf.org.ua/wp-includes/images/smilies/icon_sad.gif' alt='(' /> Так що мораль цієї басні: будьте обережними із зовнішними вінтами в ноутах&#8230;
<div>
</div>
</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=xH1QGcMb7Oc:aVJw-2Um8Sc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=xH1QGcMb7Oc:aVJw-2Um8Sc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=xH1QGcMb7Oc:aVJw-2Um8Sc:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/xH1QGcMb7Oc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/98/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/98</feedburner:origLink></item>
		<item>
		<title>Інтернет початку XXI сторіччя. Медіаконтент-хостинг</title>
		<link>http://feedproxy.google.com/~r/Itblog-ua/~3/hzgTK_3zupE/99</link>
		<comments>http://itblog.org.ua/post/99#comments</comments>
		<pubDate>Fri, 02 May 2008 11:43:21 +0000</pubDate>
		<dc:creator>graywolf</dc:creator>
		
		<category><![CDATA[Блоги]]></category>

		<guid isPermaLink="false">http://graywolf.org.ua/?p=308</guid>
		<description><![CDATA[Я не знаю як можна узагальнено назвати служби, про які піде мова далі, а тому довелось фактично придумати термін з голови, тому за його адекватність не відповідаю. Об&#8217;єднує ці служби можливість публікації різноманітного медіа (правда, не лише) контенту: відео, аудіо, документів, тощо. Звісно, далеко не всім поджібні сервіси будуть до смаку, адже завантаження тих само [...]]]></description>
			<content:encoded><![CDATA[<p>Я не знаю як можна узагальнено назвати служби, про які піде мова далі, а тому довелось фактично придумати термін з голови, тому за його адекватність не відповідаю. Об&#8217;єднує ці служби можливість публікації різноманітного медіа (правда, не лише) контенту: відео, аудіо, документів, тощо. Звісно, далеко не всім поджібні сервіси будуть до смаку, адже завантаження тих само аудіо, відео та фото можливе в кожній поважній універсальній соціальній мережі типу <a href="http://facebook.com/">Facebook</a> чи <a href="http://vkontakte.ru/">ВКонтакте</a>. Але я все ж являюсь прихильником спеціалізованих сайтів.<br />
</p>
<h4>Відео хостинг</h4>
<p>Почну, мабуть, з найбільш затребуваного та відомого широкому загалу користувачів типу контенту - відео.</p>
<p><a href="http://youtube.com/">YouTube</a>. Складно знайти інтернетичика, який не знає що таке &#8220;Ютюб&#8221;. Впевнений, для багатьох він навіть став певним синонімом відео в інтернеті. На &#8220;Ютюбі&#8221; можна викладати відео у форматах .WMV, .AVI, .MOV та .MPG. Після завантаження воно автоматично коніертуєтсья сервером у формат FLV (FLash Video). Плюсом цього формату є те, що для програвання вам потрібен лише встановлений флеш-плеєр, а також те, що сконвертоване у FLV відео має невеликий розмір (зручно для людей з необмеженим, але вузьким каналом, а також для тих, хто досі платить за трафік). Хостинг також накладає обмеження на розмір завантажуваних файлів: об&#8217;єм не більше за 1 ГБ, довжина не більше 10 хвилин. З мінусів можна назвати вельми посередню якість результуючих відеофайлів (хоча останнім часом Google, який є власником YouTube, ввів у користування нову фічу, яка дозволяє переглядати відео в кращій якості, якщо така наявна). Успіх Ютюбу надихнув багатьох людей на створення його клонів. Типовим прикладлм є, наприклад, російскьий <a href="http://rutube.com/">RuTube</a>. Крім того, YouTube нещодавно став не просто хостингом, а <a href="http://itblog.org.ua/post/44">цілою відеохостинговою платформою</a>, тобто ви можете створбвати свої власні аналогічні сайти використовуючи потужність YouTube.</p>
<p><a href="http://megavideo.com/">megavideo.com</a>. Найбільший прямий конкурент &#8220;труби&#8221;, але в той же час, на жаль, не дуже популярний. Чим саме він кращий можна дізнатись <a href="http://megavideo.com/?v=KHFS1BK2">з цього відео</a>, а для тих, кому ліньки дивитись, чи не знає англійського я зупинюсь на найцікавших моментах: більш якісне відео, відсутність обмеження на довжину ролику (хоча є оббмеження на розмір: 500 MB для безкоштовного та 5 GB для платного рахунку), доступність до завантаження оригіналу відео (лише для платних аккаунтів <img src='http://graywolf.org.ua/wp-includes/images/smilies/icon_sad.gif' alt='(' /> ), локалізація інтерфесу багатьма мовами та можливість докачки при аплоаді відео (за допомогою спеціального софту).<br />
З очевидних мінусів - менша поширеність (менше шансів знайти щсоь цікаве) та досить нав&#8217;язлива реклама: справа в тому, що вона поміщається прямо у вікно програвача і в ньому ж по центру знаходиться кнопка &#8220;Play&#8221;. Так от якщо нажати на цій кнопці у вікні відео, то відкривається реклама. Тому потрібно користуватись лише кнопкою &#8220;Play&#8221; в лівому нижньому кутку панелі програвача.</p>
<p><a href="http://veoh.com/">veoh.com</a>. Якщо ж навіть якість megavideo вас не влаштовує, то варто звернути погляд на сервіс veoh. Він пропонує потокове відео не лише у форматі FLV, а також у DivX, Quick Time та WMV, але для цього вже одним флеш-плеєром не обійтися і потрібно буде дозавантажувати інші програвачі. Ну і, звісно, трафік воно жере теж непогано, але якщо у вас є можливість дивтись відео звідси, то рекомендую veoh набільше з усього. На відміну від Труби він заточений більше на професійне відео - різноманітного виду шоу: серіали, аніме, телепередачі, тощо&#8230; із-за чого його називають навіть службою Інтернет-телебачення. Але, звісно, ніхто не забороняє вам викладати там і любительське відео. Більше того, власникам HDTV-камер взагалі несолідно було б викладати своє відео на чомусь гіршому, аніж veoh.<br />
Ну і нарешті ще один цікавий момент: &#8220;Вео&#8221; б&#8217;є &#8220;Ютюб&#8221; не лише по якості Відео, але і по сумарному часу, який проводять користувачі на сайті: в березні сумарно було прглянуто 46 мільйноів годин відео, що в два рази більше аналогічного показника у найвідвідуванішого сайту.</p>
<p><a href="http://video.google.com/">video.google.com</a>. Після придбання Гуглом Ютюба цей сайт фактично перетворився більше в пошуковик відео, аніж хостинг (хоча можливість завантажувати файли там досі присутня), але тим не менш я вирішив згадати його тут - пошук в будь-якому випадку може знадобитись, оскільки він шкає по багатьох сайтах, в тому числі і не згаданих тут.</p>
<h4>Аудіо хостинг</h4>
<p><a href="http://muxtape.com/">muxtape.com</a>. Я дізнався про цей сервіс лише нещодавно. Він до чортиків зручний. У нього до непристойного простий дизайн: ваша сторінка представляє собою просто список пісень (наприклад, <a href="http://graywolf.muxtape.com/">моя</a>), клацнувши на котру можна прослухати її, а основна сторіка має три основних посилання: завантажити пісню, редагувати списиок пісень (по дефолту воно береться з тегів, але його можна виправити) та налаштування. Але найголовніше - слухати можна без реєстрації. З мінусів - кількість завантажуваних композицій обмежена 12-ма і крім того завантажувати можна лише mp3 розміром не більше 10 MB.</p>
<p><a href="http://imeem.com/">imeem.com</a>. Занести цей сайт до списку музичних хостингів було з мого боку дещо неправильно, але вперше я познайомився з ним саме в музичному сенсі, коли качав один трек, який ніде не міг знайти. По-перше, цей сервіс все ж варто було згадати, коли я писав про соціальні мережі, але тоді я про нього ще не знав. По-друге, це не лише аудіо, а і відео- та фотохостинг. Найвизначніша його риса - це у ньому все крутиться навколо плейлистів. Тобто не окремих файлів, а їх наборів. Це може бути і альбом якогось гурту, і просто список улюблених пісень (це якщо говорити про його аудіоскладову, але плейлисти можна скаладати і до інших видів контенту, що підтримуютсья сервісом). Основний мінус - це те, що незареєстрованим користувачам для прослуховування доступні лише 30-секундні семпли, для того, щоб прослухати поністю - треба вже реєструватись. Щоправда для деякиз речей, зазвичай концертних записів, повна версія доступна без реєстрації. Обмеження на завантаження не дивився.</p>
<h4>Фотохостинг</h4>
<p><a href="http://flickr.com/">flickr.com</a>. Мова про Флікр як соцмережу вже йшла в одному з моїх попрередніх дописів, але не згадати ще раз цей сервіс (один з моїх найулюбленіших) я не можу. До речі, нещодавно Флікр до всього того став ще й хостером відео.</p>
<p>Щодо інших, то, на жаль, тут я поки лише їх перерахувати найвідоміші з невеличкими коментарями, оскільки перевірити всі в мене наразі бракує часу.<br />
<a href="http://photobucket.com/">photobucket.com</a> та <a href="">webshots.com</a> разом з Флікром утворюють трійку найпопулярніших фотосервісів. Причому якщо Фотобакет мені чомусь не дуже подобається (по-перше, дизайном, а по-друге, там навіть не стільки фото-хостинг, скільки хостинг картинок), то Вебшотс справив вельми приємні враження (і обмеження на завантаження: 1000 фоток одразу і +100 фото кожен місяць після реєстрації).</p>
<p>Ну і, звісно, не можна не згадати про <a href="http://picasaweb.google.com/">Google Picasa</a>. Щодо зручності користування, то Пікаса тут поза конкуренцією. Качаєте собі однойменний клієнт-менеджер картинок, розбиваєте все у себе на компу на альбоми, тощо, а потім пофотоково чи цілими альбомами ллєте на Пікасу у вебі. В результаті без зайвих рухів отримуєте фотоальбом в мережі. ще один плюс - я не чув про які б то не було обмеження на розміри та кількість картинок, а це вельми суттєва перевага порівняно з тим же Флікром, наприклад.</p>
<h4>Хостинг PDF-документів</h4>
<p>Тут не хочеться повторюватись, адже все вже описано до мене: і навіщо воно треба (впевнений, це найперше питання для багатьох), і які сайти пропонують подібний сервіс. Так що раджу прочитати відповідний допис Мінус-одного про <a href="http://kilesa.org.ua/2008/02/20/issuu-scribd-share/">&#8220;Issuu, Scribd і Share&#8221;</a>.
<div>
</div>
</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=hzgTK_3zupE:XIT2ZaVEEUk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/Itblog-ua?a=hzgTK_3zupE:XIT2ZaVEEUk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/Itblog-ua?i=hzgTK_3zupE:XIT2ZaVEEUk:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/Itblog-ua/~4/hzgTK_3zupE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://itblog.org.ua/post/99/feed</wfw:commentRss>
		<feedburner:origLink>http://itblog.org.ua/post/99</feedburner:origLink></item>
	<media:rating>nonadult</media:rating></channel>
</rss>
