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

<channel>
	<title>sveshnikov.ru - это наилучший источник информации по теме unix perl shell и всего такого &#187; UNIX</title>
	<atom:link href="http://alexey.sveshnikov.ru/blog/category/unix/feed/" rel="self" type="application/rss+xml" />
	<link>http://alexey.sveshnikov.ru/blog</link>
	<description>bookmarks-on-tranquilizers</description>
	<lastBuildDate>Tue, 25 May 2010 20:30:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Восхитительные грабли.</title>
		<link>http://alexey.sveshnikov.ru/blog/2010/04/28/shell_rake/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2010/04/28/shell_rake/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 19:34:08 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[PERL]]></category>
		<category><![CDATA[SHELL]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[загогулины]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/?p=171</guid>
		<description><![CDATA[Я недавно открыл для себя восхитительные грабли. Оказывается, что я ходил по ним годами, а наступил только вчера. Допустим, нам нужно скачать какой-нибудь файлик из сети, посчитать его размер и сохранить в файл. Код на perl будет примерно таким: #!/usr/bin/perl -w use strict; if (system('wget -O- http://sveshnikov.ru/httpd.sh &#124; wc -с > /tmp/size') != 0) { [...]]]></description>
			<content:encoded><![CDATA[<p>Я недавно открыл для себя восхитительные грабли. Оказывается, что я ходил по ним годами, а наступил только вчера.</p>
<p>Допустим, нам нужно скачать какой-нибудь файлик из сети, посчитать его размер и сохранить в файл.</p>
<p>Код на perl будет примерно таким:</p>
<p><code><br />
#!/usr/bin/perl -w<br />
use strict;</p>
<p>if (system('wget -O- http://sveshnikov.ru/httpd.sh | wc -с > /tmp/size') != 0) {<br />
        die "OMG! Can't count bytes in httpd.sh file!!!";<br />
}<br />
</code></p>
<p>В дальнейшем этот скрипт используется примерно так: if ./get_value; then <em>работаем с /tmp/size</em>; else <em>сообщаем куда нужно</em>; fi</p>
<p>Так вот, у этого скрипта хромает надежность. Почему? И как это сделать правильно? Жду ваших вариантов, мой &#8211; завтра :)</p>
<p><strong>UPD:</strong></p>
<p>Проблема заключается в том, что при использовании пайпов в $? окажется результат последней выполненной команды:<br />
<code><br />
$ blablabla | wc; echo $?<br />
zsh: command not found: blablabla<br />
      0       0       0<br />
0<br />
</code></p>
<p>Я решил этот вопрос с помощью bash и его опции pipefail. Пример выше я бы переписал как-то так:</p>
<p><code><br />
#!/usr/bin/perl -w<br />
use strict;                                                                                                                                                                    </p>
<p>sub my_system {<br />
      return system('bash', '-o', 'pipefail', '-c', @_);<br />
}                                                                                                                                                                              </p>
<p>unless (my_system('wget -O- http://sveshnikov.ru/httpd.sh | wc > /tmp/size') == 0) {<br />
      die "OMG! Can't count bytes in httpd.sh file!!!";<br />
}<br />
</code></p>
<p>Теперь будут отлавливаться все ошибки.<br />
В шелл-скриптах можно еще анализировать массив PIPESTATUS, в котором сохраняется exit code для всех команд ковейера, но мне показалось, что это неудобно.</p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2010/04/28/shell_rake/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Debian-пакеты с человеческим лицом на примере Zabbix 1.8</title>
		<link>http://alexey.sveshnikov.ru/blog/2010/03/29/zabbix-debianization/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2010/03/29/zabbix-debianization/#comments</comments>
		<pubDate>Sun, 28 Mar 2010 23:46:44 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[UNIX]]></category>
		<category><![CDATA[cdbs]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[debuild]]></category>
		<category><![CDATA[zabbix]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/?p=150</guid>
		<description><![CDATA[Несколько задержавшийся кросс-пост с хабрахабра, в котором я описываю пример сборки debian-пакета с использованием CDBS. Написать эту статью меня заставили две вещи: во-первых, вышел zabbix 1.8 &#8211; замечательной системы мониторинга, в которой, судя по новостям, наконец-то занялись проблемами юзабилити админского интерфейса. Во-вторых, появилось стойкое ощущение, что после статей &#8220;делаем debian-пакет на коленке&#8221;, большинство хабравчан утвердятся [...]]]></description>
			<content:encoded><![CDATA[<p><em>Несколько задержавшийся кросс-пост с хабрахабра, в котором я описываю пример сборки debian-пакета с использованием CDBS.</em></p>
<p>Написать эту статью меня заставили две вещи: во-первых, вышел zabbix 1.8 &#8211; замечательной системы мониторинга, в которой, судя по новостям, наконец-то занялись проблемами юзабилити админского интерфейса. Во-вторых, появилось стойкое ощущение, что после статей &#8220;делаем debian-пакет на коленке&#8221;, большинство хабравчан утвердятся во мнении, что debian-пакеты придумали извращенцы для извращенцев. </p>
<p>Связывает два этих события то, что zabbix 1.8 пока нет в репозиториях убунты, и когда появится не понятно, а компилить и ставить из исходников что-то на продакшн-серверах, это, конечно, недостойное джентльмена занятие. В общем, появился хороший повод продемонстрировать, что debian-пакеты &#8211; это не страшно.</p>
<p>Итак, приступим:<br />
<code><br />
apt-get install dh-make devscripts cdbs libmysqlclient-dev libcurl4-gnutls-dev<br />
wget http://sunet.dl.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Stable/1.8/<br />
tar zxvf zabbix-1.8.1.tar.gz<br />
cd zabbix-1.8.1<br />
dh_make --createorig --cdbs<br />
</code></p>
<p>Между делом, если бы мы пакетировали не zabbix, а более простую программу, которая обычно ставится с помощью ./configure; make; make install, то на этом создание пакета заканчивается. Осталось бы только собрать пакет с помощью команды <del datetime="2009-12-12T16:59:47+00:00">ar</del> debuild.</p>
<p>Но мы продолжим: откроем файл debian/control и пропишем себя, любимого, в качестве создателя пакета, и укажем, какие пакеты должны приехать на сервер вместе с установкой zabbix. Для этого нужно найти строку &#8216;Depends&#8217; и добавить в ее конец следующее: &#8220;fping, adduser, apache2, php5, php5-mysql, php5-gd&#8221;.</p>
<p>Обычно скрипт configure можно вызывать без параметров и он сгенерирует жизнеспособный конфиг, но для zabbix это не так &#8211; нужно отдельными опциями включать компиляцию серверной части и агента. Так как агент из репозитория ubuntu меня полностью устраивает, ограничимся сборкой только сервера. Для этого нужно дописать в конец файла debian/rules следующую строку:<br />
<code><br />
DEB_CONFIGURE_USER_FLAGS := --enable-server --with-mysql --with-libcurl<br />
</code></p>
<p>Сборка пакета осуществляется следующим образом: создается временная директория (debian/zabbix), в которую копируется содержимое пакета. Затем эта директория упаковывается в архив, добавляются метаданные, и все &#8211; пакет готов. Это очень грубое, но пока достаточное описание процесса. Бинарные файлы попадут в директорию debian/zabbix/usr/bin сами собой (CDBS запустит команду make install DESTDIR=debian/zabbix), а файлы php-интерфейса нам нужно туда поместить вручную. Для этого перечислим их в файле debian/install вот каким образом:<br />
<code><br />
frontends/php/* usr/share/zabbix/<br />
misc/conf/zabbix_server.conf etc/zabbix<br />
</code></p>
<p>Кроме того, для нормальной работы заббиксу нужны еще и директории для лог-файлов и локов. Они тоже являются частью пакета, поэтому создать их нужно прямо в той временной директории. Стандартный способ создания пустых директорий &#8211; перечисление их в файле debian/dirs:<br />
<code><br />
/var/log/zabbix-server<br />
/var/run/zabbix-server<br />
</code></p>
<p>Теперь дело за инит-скриптом. В комплекте с заббиксом идет инит-сктипт (misc/init.d/debian/zabbix-server), но без обработки напильником он работать не будет. Поэтому лучше его заменить скриптом из убунты (http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/karmic/zabbix/karmic/annotate/head%3A/debian/zabbix-server-mysql.zabbix-server.init), который нужно сохранить под именем debian/init.</p>
<p>Совсем не лишним было бы настроить logrotate:<br />
<code><br />
cat > debian/logrotate<br />
/var/log/zabbix-server/zabbix_server.log {<br />
    daily<br />
    rotate 7<br />
    compress<br />
    missingok<br />
    notifempty<br />
    create 0640 zabbix zabbix<br />
    sharedscripts<br />
}<br />
^D<br />
</code></p>
<p>Раз пакет мы собираем не для кого угодно, а только для себя, то почему бы и не положить конфиг апача рядом с заббикксом:<br />
<code><br />
mkdir misc/apache2-vhosts<br />
cat > misc/apache2-vhosts/zabbix<br />
<VirtualHost *><br />
        ServerName zabbix.example.com<br />
        ServerAdmin admin@example.com<br />
        DocumentRoot /usr/share/zabbix<br />
        CustomLog /var/log/apache2/zabbix_access.log combined<br />
        ErrorLog  /var/log/apache2/zabbix_error_log<br />
</VirtualHost><br />
^D<br />
echo "misc/apache2-vhosts/zabbix etc/apache2/sites-available" >> debian/install<br />
</code></p>
<p>Иногда недостаточно просто разложить файлики по файловой системе, чтобы настроить среду для исполнения программы. В таких случаях на помощь приходят preinst, postinst, prerm и postrm скрипты, которые выполняются уже на сервере, куда пакет устанавливается. Названия у них вполне понятные, пояcнить нужно только то, что &#8216;inst&#8217;, и &#8216;rm&#8217; &#8211; это фактическая распаковка или удаление содежимого пакета (все той же временной директории debian/zabbix, в нашем случае), кроме того &#8211; каждый из этих скриптов может вызываться с разными аргументами в зависимости от ситуации. Нам интересен скрипт postinst, вызывающийся с аргументом configure &#8211; нужное место скрипта можно легко найти в шаблоне postinst.ex. Приступим:</p>
<p><code><br />
cd debian<br />
mv postinst.ex postinst<br />
vim postinst<br />
</code></p>
<p>После строки configure) нужно вставить следующий код:<br />
<code><br />
          # Создадим пользователя<br />
          useradd zabbix || echo "User zabbix was not added"</p>
<p>          # Установим права на рабочие директории<br />
          chown zabbix:zabbix /var/log/zabbix-server /var/run/zabbix-server</p>
<p>          # В этой директории веб-интерфейс пытается сохранить конфиг-файл, дадим ему на это права:<br />
          chown www-data /usr/share/zabbix/conf<br />
          chmod 775 /usr/share/zabbix/conf</p>
<p>          # Настроим автозапуск сервера:<br />
          update-rc.d zabbix-server defaults</p>
<p>          # Включим новый virtualhost и перезапустим апач:<br />
          a2ensite zabbix<br />
          invoke-rc.d apache2 reload</p>
<p>      ;;</p>
<p>      abort-upgrade|abort-remove|abort-deconfigure)<br />
</code></p>
<p>Осталась одна деталь: при стандартных настройках PHP интерфейс заббикса не заведется, нужно править max_execution_time и еще несколько параметров. Если бы мы готовили пакет для домашнего сервера-торрентокачалки, то, конечно, проще было бы поправить php.ini напрямую. Но идеологически более правильно (и это очевидно при коллективной разработке, когда роли админа и разработчика разделены) поместить эти настройки тоже в пакет. Сделать это можно так:</p>
<p><code><br />
mkdir misc/php.conf<br />
cat > misc/php.conf/zabbix.ini<br />
post_max_size = 16M<br />
max_execution_time = 300<br />
mbstring.func_overload = 2<br />
^D<br />
echo "misc/php.conf/zabbix.ini   etc/php5/conf.d" >> debian/install<br />
</code></p>
<p>На этом все, можно собрать пакет с помощью команды debuild, поставить его с помощью dpkg -i
<package.deb> и apt-get install -f.</p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2010/03/29/zabbix-debianization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Магия в zsh</title>
		<link>http://alexey.sveshnikov.ru/blog/2008/11/04/zsh-magi/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2008/11/04/zsh-magi/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 22:02:47 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[SHELL]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[magic]]></category>
		<category><![CDATA[zsh]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/?p=88</guid>
		<description><![CDATA[Захотелось мне в этот чудесный выходной понедельник поагитировать за свой любимый шелл. Чем, кстати, вообще может похвастаться какой-либо шелл, имея в конкурентах такого монстра, как bash? Ведь в bash есть все, что может только пожелать обычный пользователь. А, собственно, и нечем. Поэтому разработчикам zsh пришлось пойти на хитрость и добавить в свое детище некоторое количество [...]]]></description>
			<content:encoded><![CDATA[<p>Захотелось мне в этот чудесный выходной понедельник поагитировать за свой любимый шелл. Чем, кстати, вообще может похвастаться какой-либо шелл, имея в конкурентах такого монстра, как bash? Ведь в bash есть все, что может только пожелать обычный пользователь. А, собственно, и нечем. Поэтому разработчикам zsh пришлось пойти на хитрость и добавить в свое детище некоторое количество магии :)</p>
<p>Большая ее порция досталась подсистеме автодополнения. Вот таким можно сделать дополнение имен файлов:<br />
<img src="http://alexey.sveshnikov.ru/blog/wp-content/uploads/2008/11/zsh-menu-completion.png" alt="zsh menu completion" title="zsh menu completion" width="500" height="132" class="aligncenter size-full wp-image-91" /><br />
(выбрать нужный вариант можно табом по старинке, курсорными клавишами или стандартными emacs-хоткеями)</p>
<p>А вот так &#8211; дополнение опций:<br />
<img src="http://alexey.sveshnikov.ru/blog/wp-content/uploads/2008/11/zsh-menu-completion-opts.png" alt="" title="zsh-menu-completion-opts" width="500" height="197" class="aligncenter size-full wp-image-99" /></p>
<p>Еще одна моя любимая магическая штуковина в автодополнении выглядит так: допустим, нужно подправить файл /usr/local/etc/rc.d/mysql. Пользователь bash бы ввел такую команду:<br />
<code>vim /usr/l[TAB]/e[TAB]/r[TAB]/m[TAB]</code><br />
В zsh все несколько проще, а именно:<br />
<code>vim /u/l/e/r/m[TAB]</code><br />
После нажатия [TAB] все элементы пути будут дополнены. Если вариантов несколько, можно будет вручную выбрать нужный.</p>
<p>Ну вот, я вам передал примерно 0.65 процента магии zsh. Помимо автодополнения, ее залежи находятся в подсистеме подстановок (man zshexpn), но там я сам не очень уверенно ориентируюсь. Все-таки одна из прелестей zsh заключается в том, что мне необязательно учиться им пользоваться &#8211; для начала можно ограничиться только bash-совместимым подмножеством функций, регулярно натыкаясь на приятные мелочи в реализации привычных вещей.</p>
<p>Дальнейшее чтение:<br />
<a href="http://citkit.ru/articles/1083/">обзор zsh</a> от Алексея Федорчука,<br />
Собрание хаков и идиом zsh: <a href="http://grml.org/zsh/zsh-lovers.html">zsh lovers</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2008/11/04/zsh-magi/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Пятничная загогулина (bash)</title>
		<link>http://alexey.sveshnikov.ru/blog/2008/04/11/zagogulina-bash-read/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2008/04/11/zagogulina-bash-read/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 09:41:07 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[SHELL]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[загогулины]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[загогулина]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/2008/04/11/%d0%b7%d0%b0%d0%b3%d0%be%d0%b3%d1%83%d0%bb%d0%b8%d0%bd%d0%b0-%d0%bd%d0%b0-bash/</guid>
		<description><![CDATA[Ну вот, пришло время для очередной программерской загогулины. Следующий код работать не будет: #!/usr/bin/bash echo "one two three" &#124; read a b c echo " " Что в нем не так? Я ожидаю увидеть два ответа. Первый &#8212; это просто переписать этот код так, чтобы он заработал. И второй ответ &#8212; опционально &#8212; объяснение, почему [...]]]></description>
			<content:encoded><![CDATA[<p>Ну вот, пришло время для очередной программерской загогулины. Следующий код работать не будет:</p>
<p><code>#!/usr/bin/bash<br />
echo "one two three" | read a b c<br />
echo "<$a> <$b> <$c>"</code></p>
<p>Что в нем не так?</p>
<p>Я ожидаю увидеть два ответа. Первый &#8212; это просто переписать этот код так, чтобы он заработал. И второй ответ &#8212; опционально &#8212; объяснение, почему не работает в таком виде.</p>
<p>p.s. второго ответа я пока сам не знаю, поэтому буду с интересом ждать его от вас :)<br />
p.p.s. ответивший верно, как всегда &#8211; умничка (-ца (маловероятно)).</p>
<p><b>UPD:</b> На второй вопрос ответ уже есть:<br />
<quote>gds<br />
есть мнение, что переменные, прочитанные read, остаются в переменных “экземпляра” баша, запущенного для выполнения “read a b c”, и не попадают в родительский баш, запустивший “echo … | read a b c”.</quote></p>
<p>gds&#8217;у &#8211; респект!<br />
А я понял, что в следующий раз надо постить задачки посложнее.. </p>
<p><b>UPD2</b> <s>свое решение выложу сегодня в конце рабочего дня</s><br />
<b>UPD3</b> </p>
<p>Кажется, я нечаянно сорвал рабочий день моего <a href="http://curved-hands.blogspot.com">начальника</a>, но зато он мне прислал вот такое остроумное решение:<br />
<code>str=`echo "one two three" | (read a b c; echo "a=$a; b=$b; c=$c;") `<br />
eval "$str";<br />
echo "<$a> <$b> <$c>"</code></p>
<p>Петя, ты отжог :) </p>
<p>Но на самом деле все это можно сделать несколько проще &#8211; через &#8220;here doc&#8221;:<br />
<code>read a b c  <<<`echo "one two three"`<br />
echo "<$a> <$b> <$c>"</code></p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2008/04/11/zagogulina-bash-read/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Заговор от битых кластеров (добавляем информацию для восстановления архивов с помощью par2)</title>
		<link>http://alexey.sveshnikov.ru/blog/2008/04/10/broken-cd-parchive/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2008/04/10/broken-cd-parchive/#comments</comments>
		<pubDate>Wed, 09 Apr 2008 22:08:11 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[UNIX]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[dd_rescue]]></category>
		<category><![CDATA[par2]]></category>
		<category><![CDATA[parchive]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/2008/04/10/%d0%b7%d0%b0%d0%b3%d0%be%d0%b2%d0%be%d1%80-%d0%be%d1%82-%d0%b1%d0%b8%d1%82%d1%8b%d1%85-%d0%ba%d0%bb%d0%b0%d1%81%d1%82%d0%b5%d1%80%d0%be%d0%b2-%d0%b4%d0%be%d0%b1%d0%b0%d0%b2%d0%bb%d1%8f%d0%b5%d0%bc/</guid>
		<description><![CDATA[В этой заметке я предложу способ чтения данных с поцарапанных, погрызанных собакой или обработанных шредером компакт-дисков. Итак, к делу: регулярно, при записывании данных на диск, остается некоторое количество свободного места. Лет 5 назад можно было положить диск на полочку, пометив, что еще 30 мегабайт можно забить каким-нибудь хламом, но сейчас стоимость болванки &#8211; 10 рублей, [...]]]></description>
			<content:encoded><![CDATA[<p>В этой заметке я предложу способ чтения данных с поцарапанных, погрызанных собакой или обработанных шредером компакт-дисков. </p>
<p>Итак, к делу: регулярно, при записывании данных на диск, остается некоторое количество свободного места. Лет 5 назад можно было положить диск на полочку, пометив, что еще 30 мегабайт можно забить каким-нибудь хламом, но сейчас стоимость болванки &#8211; 10 рублей, такой аргумент не действует. И, соответственно, привычку оставлять место &#8220;на потом&#8221; надо искоренять. Мне кажется, наиболее разумным было бы добавить на диск данные для восстановления &#8211; т.н. корректирующие коды Рида-Соломона, которые могут пригодится в случае, если диск будет поврежден.</p>
<p>Собственно весь заговор выглядит следующим образом:<br />
<code>#sudo aptitude install par2<br />
#man par2<br />
#cd backups<br />
#ls<br />
dump.sql.gz<br />
#par2 create -v -r10 -n1 -m500 dump.sql.gz<br />
#ls<br />
dump.sql.gz  dump.sql.gz.par2  dump.sql.gz.vol000+100.par2</code></p>
<p>Эта команда добавит 10% избыточной информации к данным, запишет все это в один файл, при этом программе par2 разрешено использовать 500 мегабайт оперативной памяти. Файлы *.par2 следует записать на диск вместе с дампом. </p>
<p>Мне эта программа понравилась, я захотел ее проверить в боевых условиях. Сделал архив размером около 400 Мб, добавил данные для восстановления &#8211;  еще 200Мб &#8211; *.par2 файлы (50% избыточность, по умолчанию &#8211; 5%). Все это я записал на CD-RW, в котором потом сделал, простите, дырку. В итоге стандартными средствами удавалось прочитать только первые 150 Кб данных. Чтобы восстановить файл нужно сначала все считать пускай с ошибками &#8211; для этого есть программа dd_rescue, которая является практчески полным аналогом dd с одним исключением &#8211; она умеет игнорировать ошибки чтения:</p>
<p><img src='http://alexey.sveshnikov.ru/blog/wp-content/uploads/2008/04/dsc_0001_1.jpg' alt='диск с дыркой' align="right" width="240"/></p>
<p><code>#sudo dd_rescue -Av -b 1048576 -B 1048576 /dev/scd0 brokencd.iso</code>(-A &#8211; заполняь нулями те участки файла, которые считать не удалось, v &#8211; verbose, -b &#8211; размер блока данных, -B &#8211; размер блока данных для проблемных областей диска)<br />
<code># sudo mount -o loop brokencd.iso mnt # монтируем получившийся образ диска<br />
# cp mnt/* dump; cd dump # копируем содержимое<br />
# par2 r archive.par2 # приводим в изначальный вид</code></p>
<p>На этом эксперимент завершился &#8211; все данные с диска восстановлены. Даже скучно.<br />
Но пример, мне кажется, весьма красноречив :)</p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2008/04/10/broken-cd-parchive/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>SSH для бэкапов и мониторинга: ограничиваем доступ.</title>
		<link>http://alexey.sveshnikov.ru/blog/2008/03/04/restricted-ssh/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2008/03/04/restricted-ssh/#comments</comments>
		<pubDate>Mon, 03 Mar 2008 23:12:57 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[SHELL]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[ssh]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/2008/03/04/restricted-ssh/</guid>
		<description><![CDATA[&#8220;Бэкап &#8211; акт проявления трусости&#8221; (c) народная мудрость Я труслив :) Во-первых, я делаю бэкапы. Во-вторых, я их боюсь передать без шифрования и, в третьих, иногда и храню их зашифрованными. Как правильно организовать передачу бэкапов с одного сервера на другой? Дампы этого блога у меня передаются по http. Они зашифрованны, да и особо ценных данных [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align: right;"><i>&#8220;Бэкап &#8211; акт проявления трусости&#8221; (c) народная мудрость</i></div>
<p>Я труслив :) Во-первых, я делаю бэкапы. Во-вторых, я их боюсь передать без шифрования и, в третьих, иногда и храню их зашифрованными.</p>
<p>Как правильно организовать передачу бэкапов с одного сервера на другой? Дампы этого блога у меня передаются по http. Они зашифрованны, да и особо ценных данных здесь нет, поэтому http меня не смущает. А как поступить с данными по-важнее? Конечно, ssh. А как при этом запретить пользователю выполнять какие-либо действия, кроме как копирования к себе бэкапа? Представим себе, что бэкап-сервер находится во вражеском дата-центре или просто вы не можете проконтролировать к нему доступ (в т.ч. физический). Нас выручит опция command файла authorized_keys.</p>
<p>Например, если необходимо предоставить доступ только к файлу backup.tgz, то в authorized_keys в самом начале соответствующей строки можно дописать следующее &#8220;command=&#8217;cat backup.tgz&#8217;&#8221;. Теперь при каждом коннекте будет автоматически выполняться команда cat backup.tgz, вам остается только перенаправить вывод в файл. Если дампов несколько, то можно написать небольшой скриптик вида:<code>#!/bin/sh<br />
read file<br />
case "$file" in<br />
"foo") cat foo.tgz ;;<br />
"bar") cat bar.tgz ;;<br />
esac</code> И прописать его в качестве команды по умолчанию. Да, не лишним было бы добавить опции no-port-forwarding, no-pty и все прочие no-*</p>
<p>Теперь копировать файл с удаленной машины можно вот такой командой:<code>echo "foo" | ssh backup@server > foo-`date +%Y-%m-%d`.tgz</code></p>
<p>Кроме как для бэкапов, такое же решение может подойти и для мониторинга. Когда нагиос стучится на удаленный сервер, чтобы собрать какую-либо статистику, полный ssh-доступ ему не нужен.</p>
<p>По-моему, все, что я описал примитивно по сложности и вместе с тем весьма надежно. Так может быть прекратим без надобности дописывать authorized_keys на серверах? Одна запись для себя, любимого, одна для бэкапов, одна для мониторинга.. ой, еще каких-то две..  дальше продолжать? :)</p>
<p>Кстати, а есть ли способы более тонко настраивать уровень доступа к ssh?</p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2008/03/04/restricted-ssh/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>О прозрачности в командной строке [pv]</title>
		<link>http://alexey.sveshnikov.ru/blog/2007/12/04/%d0%be-%d0%bf%d1%80%d0%be%d0%b7%d1%80%d0%b0%d1%87%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b2-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4%d0%bd%d0%be%d0%b9-%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%b5-pv/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2007/12/04/%d0%be-%d0%bf%d1%80%d0%be%d0%b7%d1%80%d0%b0%d1%87%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b2-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4%d0%bd%d0%be%d0%b9-%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%b5-pv/#comments</comments>
		<pubDate>Mon, 03 Dec 2007 21:01:55 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[SHELL]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[pv]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/2007/12/04/%d0%be-%d0%bf%d1%80%d0%be%d0%b7%d1%80%d0%b0%d1%87%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b2-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4%d0%bd%d0%be%d0%b9-%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%b5-pv/</guid>
		<description><![CDATA[Эта запись будет посвящена программе с лаконичным названием pv. А слово &#8220;прозрачность&#8221; пусть не ассоциируется у вас с пресловутыми compiz-fusion, тут все гораздо интереснее :) Итак, чем плох избитый пример c передачей файлов через netcat? Мне, например, не удобно то, что нет возможности наблюдать за процессом. В самом деле, возможности юниксовых шеллов в этом плане [...]]]></description>
			<content:encoded><![CDATA[<p>Эта запись будет посвящена программе с лаконичным названием pv. А слово &#8220;прозрачность&#8221; пусть не ассоциируется у вас с пресловутыми compiz-fusion, тут все гораздо интереснее :)</p>
<p>Итак, чем плох избитый пример c передачей файлов через netcat? Мне, например, не удобно то, что нет возможности наблюдать за процессом. В самом деле, возможности юниксовых шеллов в этом плане довольно скромные: с помощью tee можно сохранить поток в файл, который потом наблюдать через tail или следить за его размером командой &#8216;watch ls&#8217;. Этого достаточно для отладки, но мало для комфортной работы. </p>
<p>Поэтому программа pv просто не могла не появиться. Все очень в духе UNIX &#8211; маленькая утилитка, которая пропускает через себя поток данных и в STDERR отправляет некоторую статистику по ним. Но _как_ она это делает! Покажу на примерах:</p>
<p>Всегда хотел узнать:<br />
<code>dainichi@fujitsu:~$ cat /dev/toilet_paper | pv >/dev/shreder<br />
1.01GB 0:00:02 [ 569MB/s] [  <=>                                                                      ]</code><br />
Ага, больше десяти рулонов в секунду.. </p>
<p>Прикинемся взрослой программой с выводом а-ля wget:<br />
<code>dainichi@fujitsu:~$ cat file | pv -s `stat -c %s file` | nc so.far.away 1234<br />
 236kB 0:00:05 [ 346КB/s] [==================>                                                             ] 72%</code></p>
<p>Ограничим скорость обработки файла, чтобы mplayer не тормозил:<br />
<code>dainichi@fujitsu:~$ cat big_log | pv -L 100к | log_processor > report</code></p>
<p>Пример из мана &#8211; архивирование каталога и одновременное отображение прогрессбара<br />
<code>  (tar cf - . | pv -n -s `du -sb . | awk '{print $1}'` \<br />
     | gzip -9 > out.tgz) 2>&#038;1 | dialog --gauge 'Progress' 7 70</code></p>
<p>И, напоследок, скриншот с <a href="http://www.ivarch.com/programs/pv.shtml">домашней страницы</a> проекта:<br />
<img src='http://alexey.sveshnikov.ru/blog/wp-content/uploads/2007/12/pv.png' alt='скриншот с домашней странички проекта pv' /></p>
<p>Здорово? :) По-моему, да :) </p>
<p>Кстати. а какие еще способы &#8220;очеловечить&#8221; интерфейс командной строки вы знаете?</p>
<p><b>UPD</b> <a href="http://libc6.blogspot.com/">Андрей Афанасенко</a> поделился ссылкой вот на такое <a href="http://www.theiling.de/projects/bar.html">чудо</a>:<br />
<img src='http://alexey.sveshnikov.ru/blog/wp-content/uploads/2007/12/bar-cat-n.gif' alt='' /><br />
Написана эта программа на bash и во многих случаях ее использовать гораздо удобнее, чем pv.</p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2007/12/04/%d0%be-%d0%bf%d1%80%d0%be%d0%b7%d1%80%d0%b0%d1%87%d0%bd%d0%be%d1%81%d1%82%d0%b8-%d0%b2-%d0%ba%d0%be%d0%bc%d0%b0%d0%bd%d0%b4%d0%bd%d0%be%d0%b9-%d1%81%d1%82%d1%80%d0%be%d0%ba%d0%b5-pv/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Загадка!</title>
		<link>http://alexey.sveshnikov.ru/blog/2007/10/19/%d0%b7%d0%b0%d0%b3%d0%b0%d0%b4%d0%ba%d0%b0/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2007/10/19/%d0%b7%d0%b0%d0%b3%d0%b0%d0%b4%d0%ba%d0%b0/#comments</comments>
		<pubDate>Fri, 19 Oct 2007 11:40:43 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[SHELL]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[загогулины]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[zagogulina]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/2007/10/19/%d0%b7%d0%b0%d0%b3%d0%b0%d0%b4%d0%ba%d0%b0/</guid>
		<description><![CDATA[&#8220;Если достаточно долго лазить по карманам своих курток, можно найти практически любую сумму денег&#8221; (народная мудрость). Вот и с задачками примерно такая же ситуация &#8211; вспомнил весьма любопытную. Приятно, знаете ли, иногда посмотреть как люди мучаются над задачками, которые когда-то серьезно озаботили тебя самого :) Итак, есть следующий код: #!/bin/sh get_size() { if [ "`uname`" [...]]]></description>
			<content:encoded><![CDATA[<p>&#8220;Если достаточно долго лазить по карманам своих курток, можно найти практически любую сумму денег&#8221; (народная мудрость). Вот и с задачками примерно такая же ситуация &#8211; вспомнил весьма любопытную.<br />
Приятно, знаете ли, иногда посмотреть как люди мучаются над задачками, которые когда-то серьезно озаботили тебя самого :)</p>
<p>Итак, есть следующий код:</p>
<p><code>#!/bin/sh</p>
<p>get_size() {<br />
    if [ "`uname`" = "FreeBSD" ]; then<br />
        r=`stat -f %z $1`<br />
    else<br />
        r=`stat -c %s $1`<br />
    fi<br />
    return $r<br />
}</p>
<p>if [ -z $1 ]; then<br />
    echo "usage: print_size <file_name>";<br />
else<br />
    get_size $1;<br />
    echo $?<br />
fi<br />
</code></p>
<p>Вот результат работы скрипта:<br />
<code>asveshnikov@fe08a023fb1cc27a:~/tmp$ ls -la<br />
total 112<br />
drwxr-xr-x  2 asveshnikov asveshnikov  4096 2007-10-19 15:38 .<br />
drwxr-xr-x 85 asveshnikov asveshnikov  8192 2007-10-19 13:15 ..<br />
-rw-r--r--  1 asveshnikov asveshnikov 39781 2007-08-29 15:22 DSC02473.jpg<br />
-rw-r--r--  1 asveshnikov asveshnikov 49553 2007-08-31 17:41 DSC02481.jpg<br />
-rwxr-xr-x  1 asveshnikov asveshnikov   231 2007-10-19 15:27 print_size.sh<br />
asveshnikov@fe08a023fb1cc27a:~/tmp$ ./print_size.sh print_size.sh<br />
231<br />
asveshnikov@fe08a023fb1cc27a:~/tmp$ ./print_size.sh DSC02473.jpg<br />
39781</code></p>
<p>Как видите, абсолютно рабочий код, проверялся в Linux и FreeBSD.<br />
При этом он имеет просто ужасную.. нет, <b>чудовищную</b> проблему переносимости, которую при некоторых обстоятельствах крайне сложно обнаружить в скриптах несколько большего размера &#8211; какую?</p>
<p>p.s. угадавший первым будет умничкой :)</p>
<p>UPD: </p>
<p>Уже двое человек указали на то, что `uname` желательно взять еще и в кавычки. Вобщем, предлагаю не мелочиться, здесь проблема если и есть, то явно не &#8220;чудовищная&#8221;. Чтобы больше никого не смущать этим, подправил код. </p>
<p>Решено!</p>
<p>Михаил достаточно подробно описал проблему:</p>
<blockquote><p>Если не брать в голову отсутствие кавычек вокруг $1, а также неполный способ определения размера файла (под солярой нет stat, например), то мне кажется основная проблема в возврате значения из функции. На самом деле таким образом можно вернуть только целое, причем очень ограниченное, так как по сути возвращается код завершения функции (если не изменяет память &#8211; максимум &#8211; 256). таким образом на больших файлах получим неверное значение.</p>
<p>Решением может служить использование для возврата глобальное переменной, либо через echo.</p></blockquote>
<p>С моей стороны осталось лишь пояснить, почему проблема является &#8220;чудовищной&#8221; &#8211; она запросто может привести к порче данных, так как никакие сообщения об ошибках выводиться не будут. Ну и выглядит внешне этот код вполне надежным, так что отлавливать такой баг может быть задачей не из легких.</p>
<p>Собственно, основные проблемы возникают при портировании скрипта с sh на bash:</p>
<p><code>asveshnikov@fe08a023fb1cc27a:~/tmp$ ls -al DSC02473.jpg<br />
-rw-r--r-- 1 asveshnikov asveshnikov 39781 2007-08-29 15:22 DSC02473.jpg<br />
asveshnikov@fe08a023fb1cc27a:~/tmp$ bash print_size.sh DSC02473.jpg<br />
101</code></p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2007/10/19/%d0%b7%d0%b0%d0%b3%d0%b0%d0%b4%d0%ba%d0%b0/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Kubuntu 7.10 &amp;&amp; Enlightenment 0.17</title>
		<link>http://alexey.sveshnikov.ru/blog/2007/10/19/710/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2007/10/19/710/#comments</comments>
		<pubDate>Thu, 18 Oct 2007 21:03:09 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[UNIX]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[wm]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/2007/10/19/710/</guid>
		<description><![CDATA[Смешанные чувства: нет эйфории, которая была с 7.04: просто прервал работу на полчаса, поставил новую систему, добавил с десяток нужных мне пакетов и продолжил работу. И уже в процессе работы стал натыкаться на приятные мелочи: dolphin, который действительно мне показался шагом вперед в плане юзабельности, KNetworkManager, в котором появилось окошко статуса, strigi &#8211; служба полнотекстового [...]]]></description>
			<content:encoded><![CDATA[<p>Смешанные чувства: нет эйфории, которая была с 7.04: просто прервал работу на полчаса, поставил новую систему, добавил с десяток нужных мне пакетов и продолжил работу.</p>
<p>И уже в процессе работы стал натыкаться на приятные мелочи: dolphin, который действительно мне показался шагом вперед в плане юзабельности, KNetworkManager, в котором появилось окошко статуса, strigi &#8211; служба полнотекстового поиска по локальным файлам, и еще опера, которая теперь доступна из &#8216;Canonical partner&#8217; &#8211; репозитория.</p>
<p>Хм. Да вроде бы и все.</p>
<p>Куда больше интересного произошло на работе: нам выдали по второму монитору и видеокарте, и я пару часов потратил на приятнейшие хлопоты с подключением-настройкой всего этого добра. Выяснилось, правда, что по-нормальному со вторым монитором (в режиме xinerama) не работает ни одна из привычных мне систем: в KDE просто не получилось на него вывести никакой полезной информации, в enlightenment 0.16 обнаружился неприятный глюк &#8211; смазывался текст при манипуляциях с окнами. Наверняка все заработало бы в режиме TwinView или MergedFB, но у меня вторая видеокарта &#8211; старая ATI под слот PCI, поэтому другого варианта не было.</p>
<p><img src="http://enlightenment.sourceforge.net/Enlightenment/DR17/images/_images/DR17_shot.png" align="right" alt="скриншот с офсайта"><br />
Искать счастья я стал в e17, и.. нашел!! Я в полном восторге от нее! Все, чем мне нравился e16 там осталось, но как плюс &#8211; красивые темы, полноценная панель управления, гениальнейший диалог быстрого запуска, плагины и сносная поддержка xinerarma.</p>
<p>Недочеты следующие: во-первых, никогда нельзя с уверенностью сказать, на каком мониторе откроется новое приложение, и во-вторых, виртуальные десктопы не общие, а свой набор для каждого монитора. Как оказалось, жизнь это не сильно портит.</p>
<p>Все равно, в итоге я от самых простых вещей теперь тащусь, как удав по стекловате!! </p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2007/10/19/710/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>HTTP сервер в одну строку: версия 2.0</title>
		<link>http://alexey.sveshnikov.ru/blog/2007/08/30/bash-httpd-2/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2007/08/30/bash-httpd-2/#comments</comments>
		<pubDate>Wed, 29 Aug 2007 20:00:11 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[SHELL]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[netcat]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/2007/08/30/http-%d1%81%d0%b5%d1%80%d0%b2%d0%b5%d1%80-%d0%b2-%d0%be%d0%b4%d0%bd%d1%83-%d1%81%d1%82%d1%80%d0%be%d0%ba%d1%83-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d1%8f-20/</guid>
		<description><![CDATA[Идея с HTTP сервером на bash мне не дает покоя. Вернуться к ней меня побудила.. попытка воспользоваться старой версией: получалсь не очень :) Поэтому решил довести его до ума. Что-то дописал, что-то выкинул, полчилось следующее: :;while [ $? -eq 0 ];do nc -vlp 8080 -c'(r=read;e=echo;$r a b c;z=$r;while [ ${#z} -gt 2 ];do $r z;done;f=`$e [...]]]></description>
			<content:encoded><![CDATA[<p>Идея с <a href="http://alexey.sveshnikov.ru/blog/2006/12/23/http-сервер-размером-в-222-байта/">HTTP сервером на bash</a> мне не дает покоя.</p>
<p>Вернуться к ней меня побудила.. попытка воспользоваться старой версией: получалсь не  очень :)</p>
<p>Поэтому решил довести его до ума. Что-то дописал, что-то выкинул, полчилось следующее:<br />
<code>:;while [ $? -eq 0 ];do nc -vlp 8080 -c'(r=read;e=echo;$r a b c;z=$r;while [ ${#z} -gt 2 ];do $r z;done;f=`$e $b|sed 's/[^a-z0-9_.-]//gi'`;h="HTTP/1.0";o="$h 200 OK\r\n";c="Content";if [ -z $f ];then($e $o;ls|(while $r n;do if [ -f "$n" ]; then $e "&lt;a href=\"/$n\"&gt;`ls -gh $n`&lt;/a&gt;&lt;br&gt;";fi;done););elif [ -f $f ];then $e "$o$c-Type: `file -ib $f`\n$c-Length: `stat -c%s $f`";$e;cat $f;else $e -e "$h 404 Not Found\n\n404\n";fi)';done</code></p>
<p>Теперь по URL http://ваш_ip:8080/ можно получить доступ ко всем файлам, находящимся в текущим каталоге. Очевидных и прямолинейных способов сменить каталог нет. Как и раньше, протестировано и работает под Linux, bash 3.2.13, и с хоббитовским netcat v1.10 с поддержкой опции -с (запустите netcat -h и посмотрите. Как минимум в Ubuntu, Debian и Fedora Core такая опция есть).</p>
<p>Теперь строка занимает 434 байт,  что на 212 больше, чем прошлая версия. И мне кажется, что я с толком потратил эти байты: новый сервер обрабатывает ошибку 404, кроме того, теперь он работает без задержки, которая раньше требовалась для того, чтобы была возможность его остановить с помощью Ctrl-C. Для успешных запросов сервер отдает нормальные заголовки, с размером файла и даже с его MIME-типом. Например:</p>
<p><code>dainichi@fujitsu:~/backup$ echo "GET /6.1-RELEASE-i386-disc1.iso HTTP/1.1" | nc localhost 8080 | head -n3<br />
HTTP/1.x 200 OK<br />
Content-Type: application/x-iso9660<br />
Content-Length: 529784832</code></p>
<p>Для удобства можно сохранить его в файл и написать в .bash_profile примерно следующее:<code>alias share='sh ~/bash_httpd.sh'</code></p>
<p>Да, были попытки его еще уменьшить, но они не увенчались успехом. Есть такой вариант, но он даже больше:<br />
<code>w=while;d=done;e=echo;r=read;echo "true; $w [ @? -eq 0 ];do nc -vlp 8080 -c'($r a b c;f={$e @b|sed 's/[^a-z0-9_.-]//gi'{;h=}HTTP/1.x};o=}@h 200 OK#};c=}Content};if [ -z @f ];then($e @o;ls|(while $r n;do $e }<a href=\}/@n\}>@n</a><br />};done));elif [ -f @f ];then $e }@o@c-Type: {file -ib @f{#@c-Length: {stat -c%s @f{#};cat @f;else $e }@h 404 Not Found##404#};fi)';done"|tr "@{}#" '$`"<br />
'|sh</code> Оставил его, потому что выглядит страшно, детей пугать &#8211; самое то :)</p>
<p>Если у вас получится сэкономить еще пару байтов, то милости просим в комментаторскую :)</p>
<p><b>UPD: 03.09.2007:</b> Код обновлен, в него вошли <a href="http://sovety.blogspot.com/2007/08/21.html">исправления</a>, которые сделал тов. jetxee, за которые ему большое спасибо.</p>
<p><b>UPD: 03.09.2007:</b> Я удивлен тому факту, что эта заметка <a href="http://news2.ru/story/54417/"> попала в топ news2</a>, спасибо <a href="http://dikiy.com/blog/">dik&#8217;у</a> за то, что добавил ее. Я рад, что она многим показалась интересной.</p>
<p><b>UPD: 07.09.2007:</b> Товарищ Ed очень здорово прооптимизировал код. Вот, что у него вышло:<br />
<code>while :;do nc -p8080 -vnlc'r=read;e="echo -e";$r a b c;while [ -n "`$e $a|tr -d "\r\n"`" ];do $r a;done;f=`$e $b|sed s/.//`;h="HTTP/1.0";z="404 Not Found\n";[ -z $f ]&#038;&#038;(ls|while $r n;do [ -f $n ]&#038;&#038;$e "<a>$n</a>";done)||([ -f $f ]&#038;&#038;($e "$h 200 OK\r\nContent-Type: `file -ib $f`\n";cat $f)||$e "$h $z\n$z")';done</code></p>
<p>Работоспособность проверялась автором на таблетке Nokia N800, а у меня в Kubuntu 7.04 что-то не заработало. Сегодня вечером буду разбираться :)</p>
<p>p.s. Мне теперь стыдно из-за того, что сам не догадался использовать &#038;&#038; и || вместо if..then. :(</p>
<p>p.p.s. stay <a href="http://feeds.feedburner.com/Bookmarks-on-tranquilizers">tuned</a>!</p>
<p><b>UPD 18.08.2008:</b> О, <a href="http://habrahabr.ru/blogs/crazydev/37245/">написали</a> про это безобразие на Хабре, назвали меня извращенцем. Хулиганьё!! :)</p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2007/08/30/bash-httpd-2/feed/</wfw:commentRss>
		<slash:comments>51</slash:comments>
		</item>
	</channel>
</rss>
