<?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; Программирование</title>
	<atom:link href="http://alexey.sveshnikov.ru/blog/category/%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d0%bd%d0%b8%d0%b5/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>Code Golf</title>
		<link>http://alexey.sveshnikov.ru/blog/2010/05/26/code-golf/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2010/05/26/code-golf/#comments</comments>
		<pubDate>Tue, 25 May 2010 20:18:59 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[PERL]]></category>
		<category><![CDATA[Программирование]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/?p=182</guid>
		<description><![CDATA[Мда. Решили мы с другом поучаствовать в Code Golf на askdev.ru, с их задачкой по игре в города. Закончили буквально за три минуты до завершения конкурса, и когда было пора отправлять решение, сайт лег :)) Решение вот такое: #!/usr/bin/perl -CDAO use utf8; use List::Util qw/shuffle/; my@a=qw{Калининград Вологда Далматово Дмитров Архангельск Владивосток Краков}; {@a=shuffle@a;(grep{$a[$_-1]=~/(.)(.)$/;$a[$_]!~/^$2/i&#038;&#038;$a[$_]!~/^$1/i&#124;grep{/^$2/i}@a}1..$#a)&#038;&#038;redo} print join [...]]]></description>
			<content:encoded><![CDATA[<p>Мда.</p>
<p>Решили мы с другом поучаствовать в <a href="http://www.askdev.ru/question/1969/Code-Golf-игра-в-города/">Code Golf на askdev.ru</a>, с их задачкой по игре в города.<br />
Закончили буквально за три минуты до завершения конкурса, и когда было пора отправлять решение, сайт лег :))</p>
<p>Решение вот такое:</p>
<p><code><br />
#!/usr/bin/perl -CDAO<br />
use utf8;<br />
use List::Util qw/shuffle/;</p>
<p>my@a=qw{Калининград Вологда Далматово Дмитров Архангельск Владивосток Краков};</p>
<p>{@a=shuffle@a;(grep{$a[$_-1]=~/(.)(.)$/;$a[$_]!~/^$2/i&#038;&#038;$a[$_]!~/^$1/i|grep{/^$2/i}@a}1..$#a)&#038;&#038;redo}</p>
<p>print join ',', @a</p>
<p></code></p>
<p>По правилам этого конкурса подключение библиотек и вывод данных не учитывются, поэтому размер кода &#8211; 100 байт.</p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2010/05/26/code-golf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>Магия в 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>Чудеса!!</title>
		<link>http://alexey.sveshnikov.ru/blog/2008/06/06/hackers-sed-tetris/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2008/06/06/hackers-sed-tetris/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 08:27:10 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[SHELL]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[sed]]></category>
		<category><![CDATA[tetris]]></category>
		<category><![CDATA[чудеса]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/?p=67</guid>
		<description><![CDATA[Я страсть как люблю хакерские программки, которые удивляют самим фактом своего существования. Одна из таких: тетрис на sed&#8217;е. Это что-то невероятное! p.s. да, и я тоже, оказывается, шаблонно мыслю :)]]></description>
			<content:encoded><![CDATA[<table>
<tr>
<td align="left">
<div>
<p>Я страсть как люблю хакерские программки, которые удивляют самим фактом своего существования.</p>
<p>Одна из таких: <a href="http://uuner.livejournal.com/55238.html">тетрис на sed&#8217;е</a>. Это что-то невероятное!</p>
<p>p.s. да, и я тоже, оказывается, шаблонно мыслю :)</p>
</div>
</td>
<td align="right"><img src="http://alexey.sveshnikov.ru/blog/wp-content/uploads/2008/06/anim.gif" alt="" title="sed tetris" width="255" height="255" class="alignright size-full" /></td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2008/06/06/hackers-sed-tetris/feed/</wfw:commentRss>
		<slash:comments>3</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>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>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>
		<item>
		<title>Программерские загогулины [2]</title>
		<link>http://alexey.sveshnikov.ru/blog/2007/08/23/zagogulina2/</link>
		<comments>http://alexey.sveshnikov.ru/blog/2007/08/23/zagogulina2/#comments</comments>
		<pubDate>Thu, 23 Aug 2007 16:51:12 +0000</pubDate>
		<dc:creator>Alexey Sveshnikov</dc:creator>
				<category><![CDATA[SHELL]]></category>
		<category><![CDATA[UNIX]]></category>
		<category><![CDATA[Программирование]]></category>
		<category><![CDATA[загогулины]]></category>
		<category><![CDATA[общее]]></category>
		<category><![CDATA[quiz]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://alexey.sveshnikov.ru/blog/?p=23</guid>
		<description><![CDATA[Очередная программерская загогулина, на этот раз решение сразу не дам :) Допустим, надо выполнить какую-либо команду на нескольких хостах, перечисленных в файле. Пишу: cat file &#124; ( while read host; do ssh user@$host "command" done ) Ошибка, однако! В чем? Кто сможет разобраться в уме, не запуская код, тому респект и уважуха :) UPD: Решил [...]]]></description>
			<content:encoded><![CDATA[<p>Очередная программерская загогулина, на этот раз решение сразу не дам :)</p>
<p>Допустим, надо выполнить какую-либо команду на нескольких хостах, перечисленных в файле. Пишу:</p>
<p><code>cat file | (<br />
   while read host; do<br />
      ssh user@$host "command"<br />
   done<br />
)</code></p>
<p>Ошибка, однако! В чем?<br />
Кто сможет разобраться в уме, не запуская код, тому респект и уважуха :)</p>
<p><b>UPD: </b></p>
<p>Решил человек, скрывающийся под ником gds:</p>
<blockquote><p>поток из “cat file” будет выкушан только первой запущенной командой “ssh …”?</p></blockquote>
<p>gds, респект тебе уважуха  :)</p>
]]></content:encoded>
			<wfw:commentRss>http://alexey.sveshnikov.ru/blog/2007/08/23/zagogulina2/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
