<?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>#!/bin/sh</title>
	<atom:link href="http://binsh.ru/feed/" rel="self" type="application/rss+xml" />
	<link>http://binsh.ru</link>
	<description>Линуксоид на велосипеде с моторчиком</description>
	<lastBuildDate>Mon, 03 Oct 2016 07:32:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Boot: от Мюнхгаузена до PDP/11</title>
		<link>http://binsh.ru/2014/10/14/boot-origins.html</link>
		<comments>http://binsh.ru/2014/10/14/boot-origins.html#comments</comments>
		<pubDate>Mon, 13 Oct 2014 22:30:48 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[history]]></category>
		<category><![CDATA[multics]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://binsh.ru/?p=1246</guid>
		<description><![CDATA[<p><img src="http://binsh.ru/media/2013/07/munchausen.jpg" alt="Munchhausen" title="Munchhausen" width="290" height="388" style="float:right" />В FreeBSD Handbook в разделе про <a href="http://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/boot-introduction.html">загрузку системы</a> рассматривается известная проблема, когда только что включенный компьютер еще не в состоянии выполнять какие-либо программы, но загрузить ОС ему все же нужно. Авторы руководства проводят параллели с классической историей про барона Мюнхгаузена, когда он вытягивает себя из болота за &laquo;bootstraps&raquo;, и вспоминают известную идиому <a href="http://www.phrases.org.uk/meanings/290800.html">&laquo;to pull oneself up by one&#8217;s bootstraps&raquo;</a>.<br />
<!--more--><br />
Эту фразу часто ошибочно переводят как &laquo;вытащить себя за шнурки ботинок&raquo;, но на самом деле bootstrap (от &laquo;boot strap&raquo;, букв. &laquo;обувная петля&raquo;) — это такая деталь в виде ушка или петельки у обуви (преимущественно у высоких ботинок), расположенная над пяткой; за ушко можно потянуть и тем самым облегчить процесс надевания ботинка.  Устоявшегося русского термина, видимо, не существует.  А сама идиома означает что-то вроде &laquo;разрешить сложную ситуацию собственными усилиями&raquo;. Одно из первых известных ее появлений в печатном виде <a href="http://www.boston.com/bostonglobe/ideas/theword/2009/01/bootstraps_and.html">зафиксировано в 1834 году</a> в американской газете &laquo;Workingman&#8217;s advocate&raquo; в сообщении об очередном изобретателе вечного двигателя, дескать, мистер Мерфи теперь может сам себя перенести за bootstraps через речку Кумберланд или ограду забора. </p>
<p>Исследователи этимологии утверждают, что никакого отношения к оригинальному Мюнхгаузену это выражение не имеет, хотя бы потому, что во всех сборниках историй про барона вплоть до XX века герой вытаскивал себя из болота за волосы (точнее, за косичку парика); распространенное в англоязычном мире соотнесение Мюнхгаузена и bootstraps, возможно, происходит из английского или американского пересказа истории, в котором переводчик использовал уже устоявшуюся идиому. Нельзя также исключать и возможность всеобщего литературного помешательства, подобно, например, фразе &laquo;Мавр сделал своё дело, мавр может уйти&raquo;, <a href="http://ru.wiktionary.org/wiki/мавр_сделал_своё_дело,_мавр_может_уйти">ошибочно приписываемой</a> Шекспиру или стихотворения &laquo;Зима! крестьянин, торжествуя&#8230;&raquo;, приписываемого Некрасову.</p>
<p>С момента выхода романа &laquo;Улисс&raquo; Джеймса Джойса в 1922 году слово &laquo;bootstrap&raquo; начало широко применяться в разговорной и письменной англо-американской речи, а бутстрапперы — люди, которые сами себя сделали — и вовсе стали <a href="http://moreintelligentlife.com/content/alexander-ewing/bootstraps">частью</a>  американской национальной идеи. Впоследствии термин bootstrap неплохо прижился в <a href="http://ru.wikipedia.org/wiki/Статистический_бутстрэп">статистике</a>, <a href="http://ru.wikipedia.org/wiki/Бутстрэппинг">бизнесе</a> и некоторых компьютерных концепциях, например, теории компиляторов (применительно к проблеме &laquo;чем скомпилировать первый компилятор?&raquo;). И тут уже сложно отследить, кто у кого заимствовал столь емкий термин. Поэтому, возвращаясь к computer science, совершенно неудивительно, что для обозначения процесса загрузки, когда компьютер загружает мелкие  куски кода, &laquo;вытягивающие&raquo; в память ЭВМ еще бОльшие программы, было применено именно это словосочетание.</p>
<p>Первое печатное упоминание &laquo;bootstrap&raquo; применительно к процессу загрузки компьютера встречается в <a href="http://ru.scribd.com/doc/92259943/Buchholz-IBM-701-System-Design-Oct53">руководстве</a> по архитектуре одного из первых промышленных компьютеров под названием <a href="http://www.columbia.edu/cu/computinghistory/701.html">IBM 701 Defense Calculator</a>, выпущенному в октябре 1953 года (сам компьютер был построен в 1952 году, всего их было сделано 12 штук). Процесс загрузки описан там <a href="http://ru.scribd.com/doc/92259943/Buchholz-IBM-701-System-Design-Oct53#page=12">следующим образом</a> (комментарии в скобках <em>курсивом</em> — мои):</p>
<blockquote><p>Еще один пример того, как программы успешно заменили железо — это загрузка <em>(в оригинале — loading)</em> новой программы в компьютер. На машине есть кнопка загрузки  и переключатель источника данных, но они просто запускают процесс. Остальное реализовано с помощью техники, которую иногда называют &laquo;bootstrap technique&raquo; <em>(вот оно, первое упоминание!)</em>. Положение переключателя определяет, откуда программа будет загружена — с магнитной ленты, перфокарт или барабана. Нажатие кнопки &laquo;Load&raquo; приводит к загрузке одного полного слова <em>(одно слово — 36 бит, термин &laquo;байт&raquo; будет изобретен автором этого руководства Вернером Бухгольцем чуть позже, в 1956 году при работе над суперкомпьютером <a href="http://www-03.ibm.com/ibm/history/exhibits/mainframe/mainframe_PP7030.html">IBM 7030 Stretch</a>)</em> в адрес памяти, предварительно выставленный оператором на панели, после чего управление переходит к заданному адресу и компьютер автоматически стартует. Фактически, кнопка Load выполняет программу:</p>
<pre>+ Read x
+ Set Drum 0000 (только для барабанов)
- Copy y
+ Tr   y</pre>
<p>где <em>x</em> — идентификатор устройства ввода, выставленный на соответствующем селекторе, а <em>y</em> — адрес ячейки памяти (чётный, это важно), введенный оператором.  <em>(инструкция Tr, от &laquo;Transfer&raquo; — взять адрес следующей инструкции из половины слова по адресу, указанному в операнде)</em>. Как видите, тут просто читается слово в память и ничего больше. Однако это слово может состоять из двух инструкций, одно из которых — инструкция <em>Copy</em>, в свою очередь копирующая очередную пару инструкций в соответствующий адрес <em>(при чтении в память Copy также проверяет признак конца записи, если достигнут конец, то следующая инструкция пропускается)</em>.  Новые пары также копируют дальнейшие инструкции до тех пор, пока это необходимо. Каждая новая инструкция <em>Copy</em>, размещенная в памяти, добавляет еще одну инструкцию, так что можно построить программный цикл, который способен загрузить нужную программу в память <em>(понятия «операционная система» тогда, конечно, не существовало)</em>
</p></blockquote>
<p>Очевидно, для описания данного процесса более точного термина, чем bootstrap, придумать сложно :) C незначительными изменениями этот термин дожил до середины 1960х. В частности, в описании процесса загрузки Multics на компьютере GE 645  задействованы кнопка &laquo;BOOT&raquo; на панели оператора и программы bootstrap1 и bootstrap2. Процесс запуска системы напоминал документ десятилетней давности: оператор настраивает устройство загрузки (устройство считывания перфокарт или магнитных лент), подключает загрузочную кассету Multics и нажимает кнопку BOOT. С кассеты загружается в память и выполняется программа bootstrap1, которая выделяет дополнительные сегменты памяти по фиксированным адресам, настраивает векторы прерываний, загружает с этой же кассеты bootstrap2 и передаёт ей управление. Bootstrap2, в свою очередь, загружает еще несколько программ и в итоге все заканчивается запуском init_proc в кольце защиты ring1 (тогда как в ring0 выполняется сама операционная система). С подробностями этого захватывающего процесса можно познакомиться на странице <a href="http://www.multicians.org/boot.html">Multics Bootstrap Loading</a>.</p>
<p>Еще несколько лет после Multics компьютеры загружались в таком же полуручном режиме, когда оператор должен на пульте выставить адрес программы, считывающей загрузчик из медленной внешней памяти в определенный адрес RAM, и затем нажать спец.кнопку, после чего программа будет считана в память и выполнена. В частности, страница документации <a href="http://cm.bell-labs.com/cm/cs/who/dmr/pdfs/man71.pdf">Boot procedures&raquo;</a> (страница 5 PDF-файла по ссылке) первой версии Unix описывает такую последовательность действий для &laquo;холодной&raquo; загрузки ОС на легендарном PDP-11/20: (обратите внимание, как bootstrap уже сократилось до boot и склоняется в различных вариациях):</p>
<p>- подключить ленту UNIX Init DECtape, перемотанную в конец, в привод 0;<br />
- выставить на переключателях адрес 173740, нажать &laquo;load address&raquo;;<br />
- выставить на переключателях &laquo;1&#8243;, нажать кнопку &laquo;start&raquo;</p>
<p>В адрес памяти 0 с ленты будет прочитана программа vcboot, которая загрузит с той же ленты в адрес памяти 0 программу vcboot и передаст ей управление; vcboot прочитает, скопирует в память еще 16к слов с ленты, этим будет проинициализирована read-only часть памяти. Затем будет считана и выполнена программа bos (Bootstrap Operating System), которая, в свою очередь, выполнит процедуру &laquo;Cold UNIX&raquo;. Cold UNIX  дождется подтверждения от оператора (нажатия кнопки &laquo;continue&raquo; на пульте), после чего инициализирует RF-диск (не совсем понял, что это такое). Далее запускается из 33 блока запускается процедура, которая прочитает инициализационные файлы с ленты и только затем запустит init.</p>
<p>И лишь с распространением мини- и микрокомпьютеров и появлением нормальной постоянной энергонезависимой памяти  в середине 1970-х годов программы загрузки начали помещать в ROM. Уже в документации Unix v6, датируемой 11 февраля 1975 года и работающей на PDP-11/45 с программируемыми чипами ROM, <a href="http://wwwlehre.dhbw-stuttgart.de/~helbig/os/v6/doc/VIII/bproc.html">описывается</a> загрузка с использованием загрузчика в ПЗУ:<br />
- программа tp помещает в неиспользуемый нулевой блок ленты программу tboot или mboot (в зависимости от типа ленты — DECtape или magtape)<br />
- при загрузке ROM считывает программу загрузки с ленты, помещает ее в адрес памяти 0 и передаёт ей управление; в конечном итоге запускается <a href="http://wwwlehre.dhbw-stuttgart.de/~helbig/os/v6/doc/VIII/init.html">init</a>.<br />
- если ROM отсутствует, оператору предлагается самостоятельно внести программу чтения программы с 0 адреса ленты в память путем выставления переключателей на пульте. Тем не менее, это уже большой шаг вперед по сравнению с первыми версиями Unix.</p>
<p>А микрокомпьютер Apple I, выпущенный в 1976 году, вообще содержал чип PROM, полностью искоренявший необходимость в контроле пользователя над процессом загрузки. Правда, настройки оборудования были жестко вшиты в загрузчик, так что заменить поставляемую с компьютером операционную систему на другую не представлялось возможным. Да и железо нельзя было просто так поменять.</p>
<p>Но это, пожалуй, совсем другая история, а американская обувная поговорка начала 19 века так и прижилась в computer science.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2014/10/14/boot-origins.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moscow.Pm @2013-07-04</title>
		<link>http://binsh.ru/2013/07/03/moscow.pm-2013-07-04.html</link>
		<comments>http://binsh.ru/2013/07/03/moscow.pm-2013-07-04.html#comments</comments>
		<pubDate>Wed, 03 Jul 2013 15:43:15 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[moscow.pm]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[москва]]></category>

		<guid isPermaLink="false">http://binsh.ru/?p=1296</guid>
		<description><![CDATA[<p>Напомню, что 4 июля в 19:30 в офисе Mail.ru Group на Ленинградском проспекте (станция метро &laquo;Аэропорт&raquo;) состоится очередная встреча московских perl-разработчиков <a href="http://moscow.pm/">Moscow.pm</a>. Познакомиться с программой докладов  и зарегистрироваться можно по адресу <a href="http://corp.mail.ru/Moscow.pm">corp.mail.ru/Moscow.pm</a>. Трансляция будет на этой же странице.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2013/07/03/moscow.pm-2013-07-04.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Отключаемый she-bang в Linux-3.10</title>
		<link>http://binsh.ru/2013/07/02/shebang-linux-3.10.html</link>
		<comments>http://binsh.ru/2013/07/02/shebang-linux-3.10.html#comments</comments>
		<pubDate>Tue, 02 Jul 2013 14:17:09 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[shebang]]></category>

		<guid isPermaLink="false">http://binsh.ru/?p=1288</guid>
		<description><![CDATA[<p>В <a href="http://www.opennet.ru/openforum/vsluhforumID3/90655.html">списке новшеств</a> свежевышедшего Linux 3.10 меня заинтересовала строчка:</p>
<blockquote><p>Функциональность запуска скриптов, содержащих путь к интерпретатору в заголовке &laquo;#!&raquo;, теперь может быть собрана в виде модуля ядра, что позволяет легко запретить выполнение скриптов как программ.</p></blockquote>
<p>Воображение быстро нарисовало переменные ядра, в которые можно записать пути к разрешенным и запрещенным интерпретаторам, еще переменные, позволяющие расширенно настраивать парсинг аргументов&#8230; Всё оказалось гораздо проще.</p>
<p>С момента вынесения функциональности по парсингу she-bang из <a href="http://lxr.linux.no/#linux-old+v1.3.70/fs/exec.c#L559">fs/exec.c</a> в отдельный модуль <a href="http://lxr.linux.no/#linux-old+v1.3.71/fs/binfmt_script.c">fs/binfmt_script.c</a> в linux-1.3.71 в <a href="http://lxr.linux.no/linux-old+v1.3.71/fs/Makefile#L160">fs/Makefile</a> вплоть до недавнего времени было написано следующее:</p>
<pre># binfmt_script is always there
BINFMTS += binfmt_script.o</pre>
<p>Было это в 1996 году.</p>
<p>И только в 2013 году, в эпоху бурного развития встроенных систем, кому-то наконец понадобилось отключать поддержку выполнения внешних (по отношению к ядру) скриптов. <a href="https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/fs/Makefile?id=2535e0d723e4d7723b030f39fb350e436bdb983f">Весь</a> коммит, реализующий это, фактически только добавляет одну опцию в menuconfig и ничего больше. </p>
<p>И никаких sysctl&#8217;ов.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2013/07/02/shebang-linux-3.10.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Небольшая проблема с null filehandle в perl</title>
		<link>http://binsh.ru/2013/06/26/perl-null-fh-pitfall.html</link>
		<comments>http://binsh.ru/2013/06/26/perl-null-fh-pitfall.html#comments</comments>
		<pubDate>Wed, 26 Jun 2013 09:23:56 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://binsh.ru/?p=1229</guid>
		<description><![CDATA[<p>Рассмотрим удобную и потому частоиспользуемую конструкцию &lt;&gt; (null filehandle), имитирующую аналогичную фичу из sed и awk, когда один и тот же код может использоваться для чтения из STDIN или из файлов, чьи имена переданы в аргументах командной строки. Такая же конструкция используется в однострочниках с опцией -n:</p>
<pre>while(&lt;&gt;){
# do something with line
    chomp;
    print "got line: [$line]"\n;
}</pre>
<p>Проблема в том, что для открытия файлов perl использует встроенный оператор open в форме с двумя аргументами (например, <code>open FH, "$file"</code> где имя файла содержит и режим доступа к нему). Если название файла содержит идентификатор режима доступа, интерпретируемый функцией open (<code>"| cmd"</code>, <code>"cmd |"</code><code> или </code><code>"&gt; /path/to/file"</code>), то вместо чтения файла выполнится соответствующая команда или файл перезапишется. Так что если приведенный чуть выше код записать в файл под названием getline.pl  и выполнить с аргументом <code>"| rm -rf /"</code>, то произойдет сами понимаете что. </p>
<p>Выстрелить себе в ногу легко, еще проще этого избежать:<br />
 &#8211; использовать ключ <code>-T</code>, запрещающий использовать непроверенные данные;<br />
 &#8211; использовать ключ <code>-i .backup</code>, интерпретирующий все переданные аргументы как файлы;<br />
 &#8211; преобразовывать @ARGV перед обработкой файлов, как это сделано в <a href="https://metacpan.org/module/ARGV::readonly">ARGV::readonly</a>;<br />
 &#8211; не использовать конструкцию <code>while(&lt;&gt;)</code> в критичных скриптах;<br />
 &#8211; иногда перечитывать <a href="http://perldoc.perl.org/perlsec.html">perlsec</a>.</p>
<p>Такие дела.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2013/06/26/perl-null-fh-pitfall.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Исключение UnicodeEncodeError при записи юникода в файл в Python</title>
		<link>http://binsh.ru/2013/06/04/python-write-unicode.html</link>
		<comments>http://binsh.ru/2013/06/04/python-write-unicode.html#comments</comments>
		<pubDate>Tue, 04 Jun 2013 09:55:58 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[unicode]]></category>

		<guid isPermaLink="false">http://binsh.ru/?p=1231</guid>
		<description><![CDATA[<p>Если при попытке записи юникодной строки в файл:</p>
<pre>with open('/tmp/fail','w') as f:
   f.write(u'привет!')</pre>
<p>вываливается исключение:</p>
<pre>UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-6: ordinal not in range(128)</pre>
<p>можно не перечитывать судорожно <a href="http://docs.python.org/2/howto/unicode.html">Python Unicode HOWTO</a>, а открывать файл с помощью функции <a href="http://docs.python.org/2/library/codecs.html#codecs.open">codecs.open</a>, обеспечивающей прозрачное перекодирование из внутреннего формата python в нужную кодировку:</p>
<pre>import codecs
with codecs.open('/tmp/success','w','utf-8') as f:
   f.write(u'привет!')</pre>
]]></description>
		<wfw:commentRss>http://binsh.ru/2013/06/04/python-write-unicode.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Вышел mitmproxy 0.9</title>
		<link>http://binsh.ru/2013/05/16/mitmproxy-0.9.html</link>
		<comments>http://binsh.ru/2013/05/16/mitmproxy-0.9.html#comments</comments>
		<pubDate>Thu, 16 May 2013 11:05:40 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[mitmproxy]]></category>

		<guid isPermaLink="false">http://binsh.ru/?p=1217</guid>
		<description><![CDATA[<p>Пока я писал <a href="http://binsh.ru/2013/05/16/mitmproxy.html">обзор</a> интерактивного прокси-сервера mitmproxy, основываясь на старой версии 0.8.1, <a href="http://corte.si/posts/code/mitmproxy/announce0_9/index.html">был анонсирован</a> выход нового мажорного релиза 0.9 с множеством улучшений интерфейса и программной части:</p>
<ul>
<li>включен по умолчанию режим upstream certs (когда mitmproxy получает детали сертификата у родительского сервера);</li>
<li>добавлен специальный WSGI-контейнер для размещения веб-приложений прямо внутри прокси;</li>
<li>поддержка полностью прозрачного проксирования для Linux и OSX;</li>
<li>часть кода вынесена в общую для mitmproxy и веб-сервера <a href="http://pathod.net">pathod</a>  библиотеку <a href="http://github.com/cortesi/netlib">netlib</a>;</li>
<li>полная поддержка SNI — расширения протокола TLS, в котором клиент имеет возможность указать, имя хоста, к которому он подключается;</li>
<li>цветовые схемы оформления для светлых и тёмных терминалов;</li>
<li>запись потоков в файл по мере поступления (кнопка &laquo;W&raquo;);</li>
<li>в язык фильтров добавлены операторы ~d (поиск по домену) и ~a (по содержимому: js, css, изображения);</li>
<li>режим следования (&laquo;F&raquo;), для слежения за потоками по мере их поступления а-ля tail -f;</li>
<li>опция &#8211;dummy-certs для указания и сохранения каталога dummy-сертификатов;</li>
<li>воспроизведение потока сервера из текущего буфера;</li>
<li>множество улучшений в просмотрщике контента, теперь есть вьюеры для AMF, HTML, JSON, Javascript, изображений, XML, URL-encoded форм, а также шестнадцатеричный режим и режим &laquo;сырого&raquo; просмотра;</li>
<li>возможность установки дополнительных заголовков, которые добавляются к запросам и ответам при соответствии шаблонам;</li>
<li>графический редактор компонентов пути;</li>
<li>набор стандартных строк User-Agent, которые можно использовать в редакторе заголовков;</li>
<li>аутентификация для ограничения доступа к прокси;</li>
</ul>
<p>Также анонсирован выход HTTP-сервера <a href="http://corte.si/posts/code/pathod/announce0_9.html">Pathod 0.9</a>.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2013/05/16/mitmproxy-0.9.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>mitmproxy — консольный firebug</title>
		<link>http://binsh.ru/2013/05/16/mitmproxy.html</link>
		<comments>http://binsh.ru/2013/05/16/mitmproxy.html#comments</comments>
		<pubDate>Thu, 16 May 2013 09:41:52 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[mitmproxy]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[рабочие будни]]></category>

		<guid isPermaLink="false">http://binsh.ru/?p=1177</guid>
		<description><![CDATA[<p>Firebug — отличная штука, когда дело касается анализа запросов в конкретном браузере, но часто приходится отлаживать не связанные ни с каким браузером клиент-серверные приложения, общающиеся с сервером по протоколу HTTP. Я пишу тесты HTTP API на python, и часто ощущается необходимость удобного просмотра трафика от меня к серверу. Для админов и веб-разработчиков может быть актуальным мониторинг трафика от nginx к HTTP-бэкенду. </p>
<p>Общепринятые инструменты, прослушивающие трафик (tcpdump, ngrep, tshark), либо не поддерживают http в полной мере (хочется, как минимум, нормальное отображение заголовков по одному на строке и отображение сжатого gzip или deflate контента), либо в силу своей универсальности слишком сложны в настройке и использовании в контексте конкретной задачи (wireshark). Да и не всегда есть возможность перевести интерфейс в состояние promisc, чтобы получать трафик, хотя бы по причине недостатка прав.</p>
<p>Установка nginx, squid, 3proxy или любого другого известного прокси-сервера также связана с многими трудностями, да и не везде можно нормально настроить полное журналирование заголовков запросов и ответов.</p>
<p>Идеальным решением был бы сервис, работающий как HTTP-прокси, способный работать с правами пользователя, не требующий множества действий для конфигурации логов и запуска, отображающий куда-нибудь заголовки запросов и ответов в человекочитаемом формате, а при необходимости — и тела запросов и ответов.</p>
<p>После недолгих поисков нашел инструмент, идеально соответствующий таким требованиям: <a href="http://mitmproxy.org">mitmproxy</a>&nbsp;— прокси-сервер, написанный на Python, умеющий перехватывать HTTP и HTTPS, менять трафик на лету, воспроизводить записанный трафик, декодировать и отображать основные типы документов.  Под катом — подробный обзор.<br />
<!--more--></p>
<p>Для его запуска необходимо всего ничего:</p>
<p>- <b>поставить</b> mitmproxy одним из способов:</p>
<pre>sudo aptitude install mitmproxy</pre>
<p>или </p>
<pre>easy_install mitmproxy</pre>
<p>или </p>
<pre>pip install mitmproxy</pre>
<p>или</p>
<pre>wget -O - http://mitmproxy.org/download/mitmproxy-0.8.1.tar.gz |tar -xf -
cd mitmproxy-0.8.1
python setup.py build
python setup.py install</pre>
<p>Последние три годятся даже в случае, когда нет root&#8217;а на машине и окружение python установлено локально, например,  по <a href="http://peak.telecommunity.com/DevCenter/EasyInstall#creating-a-virtual-python">этому</a> руководству;</p>
<p>- <b>запустить</b> в режиме прокси-сервера:</p>
<pre>mitmproxy -p 3128 -a 127.0.0.1</pre>
<p>Если все зависимости установлены, появится пустое окно, выйти из него можно по кнопке Q или Ctrl+C, а по знаку вопроса &laquo;?&raquo; можно получить справку;</p>
<p>- указать своему приложению <b>использовать</b> прокси для HTTP и HTTPS, например, с помощью переменных окружения:</p>
<pre>$ HTTP_PROXY=http://127.0.0.1:3128 HTTPS_PROXY=http://127.0.0.1:3128 python testproxy.py</pre>
<p>Теперь, если все сделано правильно, в окне mitmproxy появится лог запросов.</p>
<p>Чтобы не быть голословным, приведу пример небольшого скрипта с микротестом сервиса отладки запросов <a href="http://httpbin.com">httpbin.com</a>. Для его запуска требуется установленная библиотека <a href="http://www.python-requests.org/">requests</a>. Код неидеален, т.к. его цель — не протестировать весь httpbin.com, а просто проиллюстрировать работу прокси-сервера:</p>
<p><script src="https://gist.github.com/vbrednikov/5582547.js"></script></p>
<p>После того, как я запустил скрипт указанным выше способом, в mitmproxy появились запросы:</p>
<p><img src="http://binsh.ru/media/2013/05/6da39.png" alt="" title="6da39" class="aligncenter size-medium wp-image-1180" width="536" /></p>
<p>По ним можно перемещаться стрелками и выбирать для просмотра нажатием кнопки Enter:</p>
<p><img src="http://binsh.ru/media/2013/05/de8df.png" alt="" title="de8df" width="536" class="aligncenter size-full wp-image-1186" /></p>
<p>Между вкладками Request/Response можно перемещаться кнопкой Tab. Перехваченный Response:</p>
<p><img src="http://binsh.ru/media/2013/05/03b3a.png" alt="" title="03b3a" width="536" height="436" class="aligncenter size-full wp-image-1188" /></p>
<p>Выход в основное окно — &laquo;q&raquo;, очистка истории запросов, если их много — &laquo;C&raquo;. Отфильтровать запросы по регэкспу — кнопка &laquo;l&raquo; (первая буква в слове &laquo;limit&raquo;).</p>
<p>С помощью фильтра i можно перехватывать и задерживать запросы по различным условиям и оперативно исправлять в них данные или вовсе обрывать. Например, я нажал кнопку &laquo;i&raquo;, задал выражение &laquo;post&raquo;, и при отправке запроса к httpbin.com/post соединение было приостановлено до одобрения. Одобрить можно отдельно request и response, предварительно отредактировав нужные данные. На скриншоте я одобрил request, а response сейчас будем редактировать (всё это время скрипт ожидает соединения).</p>
<p>Нажал &laquo;e&raquo;, внизу появился выбор, что редактируем: код и сообщение ответа (&laquo;HTTP 200 OK&raquo;), заголовок или тело ответа. В скриншоте выбрано тело ответа:</p>
<p><img src="http://binsh.ru/media/2013/05/32f01.png" alt="" title="32f01" width="536" height="436" class="aligncenter size-full wp-image-1190" /></p>
<p>В args с помощью внешнего редактора (конечно, vim) заменили <code>"q": "1"</code> на <code>"q": "100500"</code>:</p>
<p><img src="http://binsh.ru/media/2013/05/4d960.png" alt="" title="4d960" width="536" height="436" class="aligncenter size-full wp-image-1191" /></p>
<p>И нажали &laquo;a&raquo;. В результате соединение завершилось, клиенту вернулся &laquo;неправильный&raquo; ответ и тестовая функция завершилось с ошибкой:</p>
<pre>$ HTTP_PROXY=http://localhost:3128 HTTPS_PROXY=http://localhost:3128 python u.py
F
======================================================================
FAIL: test_cookie_post (__main__.TestHttpBin)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "u.py", line 19, in test_cookie_post
    self.assertEqual(response.json()['args']['q'], '1')
AssertionError: u'100500' != '1'

----------------------------------------------------------------------
Ran 1 test in 53.721s

FAILED (failures=1)
</pre>
<p>Конечно, сидеть и вручную переписывать данные неправильно (да и вообще неправильно переписывать данные, но мы тестировщики, нам можно), поэтому mitmproxy предоставляет возможность автоматического исправления пропускаемого трафика. Подробно эти и многие другие возможности  <a href="http://mitmproxy.org/doc/replacements.html">описаны</a> в <a href="http://mitmproxy.org/doc/scripts.html">документации</a>.</p>
<p>Такой функциональности было бы более чем достаточно для отладки небраузерных HTTP-клиентов, однако аббревиатура &laquo;MiTM&raquo; (man in the middle) всё же ассоциируется с перехватом SSL-трафика, и тут mitmproxy на высоте! Указав дополнительную переменную окружения
<pre>HTTPS_PROXY=http://localhost:3128</pre>
<p>, можно перенаправить все запросы к https через запущенный прокси, и они также будут видны. Конечно, при этом клиенту будет отдаваться самоподписанный сертификат, и нормальная ssl-библиотека будет ругаться на неправильную подпись, однако в отладочных целях можно подавить эту ругань (опция &#8216;verify=None&#8217; у requests), а в Firefox и вовсе импортировать сертификат CA mitmproxy, как написано <a href="http://mitmproxy.org/doc/certinstall/firefox.html">здесь</a>.</p>
<p>Вкратце коснусь некоторых фич mitmproxy, полезных в основном для тестировщиков, особенно для pen-tester&#8217;ов:<br />
- <a href="http://mitmproxy.org/doc/features/anticache.html">anticache</a>: подавление заголовков if-modified-since и if-none-match в запросе, таким образом гарантируется полный ответ от сервера, даже если браузер сообщает, что документ есть в кэше;<br />
- <a href="http://mitmproxy.org/doc/features/clientreplay.html">client-side replay</a>: можно записывать трафик от клиента к серверу и воспроизводить его, например, записать сессию получения каких-нибудь данных и при необходимости получать их, почти полностью имитируя при этом клиента;<br />
- <a href="http://mitmproxy.org/doc/features/serverreplay.html">server-side replay</a>: можно воспроизводить для клиента записанные ранее ответы от сервера, если параметры и/или заголовки запроса соответствуют заданным;<br />
- <a href="http://mitmproxy.org/doc/features/replacements.html">замены</a>: можно заменять один текст на другой в разных местах. В документации предлагается use-case для этой фичи: заменять XSS на длинный код эксплойта из файла;<br />
- добавление дополнительных <a href="http://mitmproxy.org/doc/features/setheaders.html">заголовков</a>, <a href="http://mitmproxy.org/doc/features/sticky.html">кук или авторизации</a> ко всем проксируемым запросам<br />
- режим <a href="http://mitmproxy.org/doc/features/reverseproxy.html">reverse proxy</a>, когда все запросы отсылаются к вышестоящему серверу. В таком режиме mitmproxy можно использовать как временную прослойку между nginx и http upstream и в реальном времени наблюдать  и перехватывать запросы. Конечно исключительно в режиме отладки или на тестовом сервере, в production такое пускать нельзя из-за периодических падений.</p>
<p>Удачной отладки!</p>
<p>P.S. Если при запуске mitmproxy возникает ошибка импорта Image из PIL, например:</p>
<pre>
Traceback (most recent call last):
  File "/home/user/bin/mitmproxy", line 5, in <module>
....
  File "/home/user/lib/python2.7/site-packages/mitmproxy-0.8.1-py2.7.egg/libmproxy/console/flowview.py", line 18, in </module><module>
    import common, grideditor, contentview
  File "/home/user/lib/python2.7/site-packages/mitmproxy-0.8.1-py2.7.egg/libmproxy/console/contentview.py", line 3, in &lt;module&gt;
    from PIL import Image
ImportError: No module named PIL
</module></pre>
<p>это значит, что у вас устаревшая версия mitmproxy и нужно применить <a href="https://github.com/cortesi/mitmproxy/commit/15c367ffb499daab3cdf9dace618bd484bc38103">патч</a>.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2013/05/16/mitmproxy.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>История команды ping</title>
		<link>http://binsh.ru/2013/02/14/ping.html</link>
		<comments>http://binsh.ru/2013/02/14/ping.html#comments</comments>
		<pubDate>Thu, 14 Feb 2013 12:46:04 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[ping]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[история]]></category>
		<category><![CDATA[Ссылки]]></category>

		<guid isPermaLink="false">http://binsh.ru/?p=1144</guid>
		<description><![CDATA[<p>Не могу не сохранить здесь ссылку на <a href="http://habrahabr.ru/post/169401/">перевод</a> <a href="http://ftp.arl.army.mil/~mike/ping.html">истории команды ping</a>, написанной ее автором Mike Muuss. Кстати, согласно <a href="http://en.wikipedia.org/wiki/Mike_Muuss">википедии</a>, он же предложил концепцию default gateway, что вроде бы увековечено в <a href="https://tools.ietf.org/html/rfc898">RFC898 &laquo;Gateway special interest group meeting notes&raquo;</a>. </p>
<p>Также заслуживает внимания его <a href="http://ftp.arl.army.mil/~mike/">персональная страница</a>, содержащая некоторое количество интересных материалов об <a href="http://ftp.arl.army.mil/~mike/comphist/">истории computer science</a>, в частности, воспоминания участников разработки и эксплуатации первого компьютера общего назначения <a href="http://ftp.arl.army.mil/~mike/comphist/46eniac-report/chap1.html">ENIAC</a>. Кстати, впервые ENIAC был представлен публике ровно 67 лет назад, 14 февраля 1946 года.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2013/02/14/ping.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Раскладка клавиатуры Russian Typewriter</title>
		<link>http://binsh.ru/2013/02/12/russian-typewriter.html</link>
		<comments>http://binsh.ru/2013/02/12/russian-typewriter.html#comments</comments>
		<pubDate>Tue, 12 Feb 2013 14:44:17 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[unix]]></category>
		<category><![CDATA[vi]]></category>
		<category><![CDATA[история]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=334</guid>
		<description><![CDATA[<div style="float:right;margin: 0 0 5px 5px"><a href="http://binsh.ru/media/2013/02/DEC_Decwriter-II_LA36_front.jpg"><img src="http://binsh.ru/media/2013/02/DEC_Decwriter-II_LA36_front-300x225.jpg" alt="DEC Decwriter-II LA36" title="DEC Decwriter-II LA36" width="300" height="225" class="size-medium wp-image-1125" /></a>
<div align="center" style="font-size:small">клавиатура Decwriter-II LA36</div>
</div>
<p>  Однажды, на моей позапрошлой работе (2008 год), к нам приезжал клиент из Франции, которому мы установили демо-версию нашего продукта, работавшего исключительно под RedHat 9. Продукт был русский, локаль для всех иностранных клиентов была en_US, и выяснилось, что региональные настройки не соответствовали французскому языку и, в частности, французской раскладке <a href="http://ru.wikipedia.org/wiki/AZERTY">AZERTY</a>. Я тогда битый час, сидя за этим ноутом, разбирался в редхатовских скриптах loadkeys, setsysfont, setfont, consolechars, вызывавших друг друга по очереди, параллельно пытаясь привыкнуть к непривычному расположению клавиш a, z, q и m, а также необходимости нажимать Shift для ввода цифр и не нажимать его для ввода двоеточия и вертикальной палки &laquo;|&raquo;. Правда, удобство ввода двоеточия &laquo;:&raquo; в vim меня очень впечатлило и я даже начал что-то подозревать о причинах использования именно его для перехода в командный режим. Короче говоря, локаль поменял, раскладку настроил и клиент уехал довольный тестировать результаты наших усилий.</p>
<p>Под впечатлением от французской чудо-клавиатуры, вспомнив заодно известную статью Артемия Лебедева «<a href="http://www.artlebedev.ru/kovodstvo/sections/105/">трагедия запятой</a>», поменял  обычную русскую раскладку на «русская печатная машинка». Процесс привыкания к новым кнопкам занял неделю: спинной мозг боролся с  необычным расположением спецсимволов, зато через полтора месяца эксперимента выяснилось, что набирать русские нетехнические тексты стало намного удобнее: для ввода знаков препинания, использующихся в русском языке чаще, чем в английском, не требуется нажимать Alt, Shift или что-нибудь ещё, и расположение буквы «Ё» гораздо лучше (слева от правого шифта).  С тех пор и использую эту раскладку. </p>
<p>Кстати, в вышеупомянутом параграфе Лебедев грешит против истины в отступлении «Существует раскладка, имитирующая русскую пишущую машинку. Ее отличие в том, что знаки препинания находятся в верхнем ряду клавиш, но не в нижнем регистре. Это еще хуже, потому что в этом случае и точку надо набирать с подъемом каретки (shift).» Наоборот, в этой раскладке спецсимволы доступны как раз в нижнем регистре.</p>
<p>P.S. на самом деле двоеточие для перехода в командный режим vim пришло из vi, автор которого, Билл Джой, тестировал его на <a href="http://www.vintagecomputer.net/digital/PDP11-40/">PDP 11/40</a>, PDP 11/45, PDP 11/70 (см. <a href="http://roguelife.org/~fujita/COOKIES/HISTORY/1BSD/exrefm.pdf">William N. Joy, Ex reference manual, November, 1977</a>, <nobr>стр. 29­-30</nobr>), для доступа к которым использовался терминал, соответствующий требованиям стандарта ANSI X4.14-1971, регламентирующего раскладки клавиатуры, например, выпущенный в 1972 году Decwriter-II LA36. На фотографии в начале поста отчетливо видно, что двоеточие находится там же, где и сейчас, и доступно в верхнем регистре, т.е. требует нажатия Shift. <a href="http://www.columbia.edu/cu/computinghistory/vt100-keyboard.jpg">Аналогичную раскладку</a> использовал и легендарный терминал <a href="http://www.columbia.edu/cu/computinghistory/vt100.html">DEC VT100</a>. Поэтому домыслы о выборе двоеточия из-за его доступности в нижнем регистре подтверждения не нашли.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2013/02/12/russian-typewriter.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Если в Ubuntu 12.10 не собираются модули dkms после обновления</title>
		<link>http://binsh.ru/2012/11/19/quantal-dkms-failed.html</link>
		<comments>http://binsh.ru/2012/11/19/quantal-dkms-failed.html#comments</comments>
		<pubDate>Mon, 19 Nov 2012 10:08:13 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[dkms]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://binsh.ru/?p=1106</guid>
		<description><![CDATA[<p>Решил посмотреть, насколько сильно Ubuntu изменилась с тех пор, как я ее в последний раз использовал, поставил на Eee PC 1215n 12.10 и тут же столкнулся с преотвратной багой. Для wireless-адаптера Broadcom Corporation BCM4313 при установке системы был установлен и собран с помощью dkms проприетарный драйвер bcmwl (пакет bcmwl-kernel-source), но при первом же обновлении ядра до 3.5.0-18 сеть перестала работать, т.к. dkms не смог собрать этот драйвер в отсутствие Module.symvers и других файлов, генерируемых при сборке ядра. В ходе экспериментов с dkms слетел также и модуль для предыдущего ядра 3.5.0-17, так что данный экземпляр ОС остался без сети (не считая загрузки в альтернативную систему, livecd и еще одного домашнего компьютера). </p>
<p>Помогла установка пакета linux-headers-generic, содержащего все необходимые файлы для сборки модулей ядра. Баги на launchpad: <a href="https://bugs.launchpad.net/ubuntu/+source/nvidia-graphics-drivers-updates/+bug/1068341">bugs.launchpad.net/ubuntu/+source/nvidia-graphics-drivers-updates/+bug/1068341</a>, <a href="https://bugs.launchpad.net/ubuntu/+source/ubiquity/+bug/1068488">bugs.launchpad.net/ubuntu/+source/ubiquity/+bug/1068488</a> и далее по ссылкам.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2012/11/19/quantal-dkms-failed.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Нижний Новгород в погодном апплете Gnome</title>
		<link>http://binsh.ru/2012/02/06/nnov_libgweather.html</link>
		<comments>http://binsh.ru/2012/02/06/nnov_libgweather.html#comments</comments>
		<pubDate>Mon, 06 Feb 2012 08:28:29 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[нижний новгород]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=1098</guid>
		<description><![CDATA[<p>Для того, чтобы наблюдать погоду в верхней панели, всю жизнь тщательно вбивал координаты нашего нижегородского аэропорта (ICAO: UWGG) в /usr/share/libgweather/locations.xml, т.к. в списке городов Нижнего Новгорода нет и не было, а при вводе &laquo;nizh&raquo; показывался только Nizhnevartovsk. На прошлой неделе решил окончательно разобраться с этим вопросом и обнаружил, что вместо Нижнего Новгорода нужно искать Стригино — поселок в черте города, поделившийся названием с аэропортом.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2012/02/06/nnov_libgweather.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Политическая позиция</title>
		<link>http://binsh.ru/2011/12/02/elections.html</link>
		<comments>http://binsh.ru/2011/12/02/elections.html#comments</comments>
		<pubDate>Fri, 02 Dec 2011 11:44:47 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[выборы]]></category>
		<category><![CDATA[политика]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=1092</guid>
		<description><![CDATA[<p>Пойду 4 декабря голосовать против партии &laquo;Единая Россия&raquo; по следующим причинам:</p>
<p>1. Государственная дума — место для политических дискуссий;<br />
2. Партия, которая:<br />
 — имеет своей целью обеспечение беспрепятственного прохождения абсолютно любых законопроектов в государственной думе;<br />
 — монополизировала и фактически подменила собой власть;<br />
 — законодательно обеспечила большинство в последующих думах при отсутствии фактической поддержки среди населения;<br />
 — без стеснения использует административный ресурс для обеспечения своей поддержки на выборах, явно нарушая законодательство, и ей сходит это с рук;<br />
 — указывает в своих заслугах то, что она, являясь властью, и так должна делать;<br />
 — грозит лишением федеральных денег целых регионов за то, что часть их населения не поддерживает;<br />
— в начале своих федеральных и региональных списков указывает людей, которые заведомо не будут и не могут быть депутатами, а иногда даже и не являются членами этой партии —</p>
<p>не должна иметь большинство в Думе.</p>
<p>3. Коррупция, fail&#8217;ы космической программы, провалы конкурсов на поставки военной техники союзникам, провал совместных тихоокеанских учений с Индией, слабость внешней политики, сомнительная олимпиада — всё это тоже заслуги Единой России.</p>
<p>Сходите на выборы и явно выразите свое мнение, иначе неявно ваш голос отойдет этой партии.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2011/12/02/elections.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Пересборка ruby gem на примере hiredis в FreeBSD</title>
		<link>http://binsh.ru/2011/11/06/gem-hiredis-freebsd.html</link>
		<comments>http://binsh.ru/2011/11/06/gem-hiredis-freebsd.html#comments</comments>
		<pubDate>Sun, 06 Nov 2011 17:30:18 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[freebsd]]></category>
		<category><![CDATA[рабочие будни]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=1076</guid>
		<description><![CDATA[<p>Для тех админов, кому <s>лень</s> некогда копаться во внутренностях ruby и гуглить невнятные ошибки, но надо срочно поставить ruby gem, отсутствующий в портах. В моем случае — hiredis (ruby обвязка для одноименной библиотеки доступа к БД redis). Установка методом
<pre>gem install hiredis</pre>
<p> не работает, т.к. где-то внутри жестко зашито название утилиты make, а FreeBSD-версия  /usr/bin/make серьезно отличается по синтаксису от GNU Make, который все привыкли использовать, поэтому в STDERR сыпятся ошибки:</p>
<pre># gem install hiredis
Fetching: hiredis-0.4.1.gem (100%)
Building native extensions.  This could take a while...
ERROR:  Error installing hiredis:
	ERROR: Failed to build gem native extension.

        /usr/local/bin/ruby18 extconf.rb
"Makefile", line 11: Missing dependency operator
"Makefile", line 21: Need an operator
"Makefile", line 22: Missing dependency operator
"Makefile", line 33: Need an operator
"Makefile", line 43: Need an operator
"Makefile", line 44: Need an operator
"Makefile", line 82: Need an operator
"Makefile", line 86: Need an operator
"Makefile", line 88: warning: duplicate script for target "hiredis-example-ae" ignored
"Makefile", line 89: Need an operator
make: fatal errors encountered -- cannot continue
creating Makefile

make
cc -I. -I/usr/local/lib/ruby/1.8/amd64-freebsd8 -I/usr/local/lib/ruby/1.8/amd64-freebsd8 -I. -I/usr/include -fPIC -I/usr/include -O2 -pipe -fno-strict-aliasing -fPIC -I/usr/local/lib/ruby/gems/1.8/gems/hiredis-0.4.1/vendor/hiredis -c connection.c
cc -I. -I/usr/local/lib/ruby/1.8/amd64-freebsd8 -I/usr/local/lib/ruby/1.8/amd64-freebsd8 -I. -I/usr/include -fPIC -I/usr/include -O2 -pipe -fno-strict-aliasing  -fPIC  -I/usr/local/lib/ruby/gems/1.8/gems/hiredis-0.4.1/vendor/hiredis -c hiredis_ext.c
cc -I. -I/usr/local/lib/ruby/1.8/amd64-freebsd8 -I/usr/local/lib/ruby/1.8/amd64-freebsd8 -I. -I/usr/include    -fPIC -I/usr/include -O2 -pipe -fno-strict-aliasing -fPIC  -I/usr/local/lib/ruby/gems/1.8/gems/hiredis-0.4.1/vendor/hiredis -c reader.c
cc -shared -o hiredis_ext.so connection.o hiredis_ext.o reader.o -L. -L/usr/local/lib -Wl,-R/usr/local/lib -L. -L/usr/lib  -rpath=/usr/lib:/usr/local/lib -pthread -rdynamic /usr/local/lib/ruby/gems/1.8/gems/hiredis-0.4.1/vendor/hiredis/libhiredis.a -Wl,-soname,hiredis_ext.so   -Wl,-R -Wl,/usr/local/lib -L/usr/local/lib -lruby18  -lcrypt -lm -L/usr/lib  -rpath=/usr/lib:/usr/local/lib -pthread
cc: /usr/local/lib/ruby/gems/1.8/gems/hiredis-0.4.1/vendor/hiredis/libhiredis.a: No such file or directory
*** Error code 1

Stop in /usr/local/lib/ruby/gems/1.8/gems/hiredis-0.4.1/ext/hiredis_ext.

Gem files will remain installed in /usr/local/lib/ruby/gems/1.8/gems/hiredis-0.4.1 for inspection.
Results logged to /usr/local/lib/ruby/gems/1.8/gems/hiredis-0.4.1/ext/hiredis_ext/gem_make.out
</pre>
<p>GNU-версия make в freebsd называется gmake. Чтобы исправить вызов make в gem&#8217;е, пришлось его пересобрать. Вот полная версия установки пакета:</p>
<pre>$ mkdir ~/hiredis &#038;&#038; cd ~/hiredis
$ gem fetch hiredis  # в текущем каталоге появляется файл hiredis-0.4.1.gem
Downloaded hiredis-0.4.1
$ gem unpack hiredis-0.4.1.gem
Unpacked gem: '/home/bvk/hiredis/hiredis-0.4.1'
$ gem spec  hiredis-0.4.1.gem > hiredis.spec # извлекли спецификацию gem'а, по которой будем собирать пакет
$ cd hiredis-0.4.1
# тут в ext/hiredis_ext/extconf.rb нужно поменять "make static" на "gmake static",
# а в Rakefile "make clean" на "gmake clean"
# собираем пакет
$ gem build ../hiredis.spec
WARNING:  description and summary are identical
  Successfully built RubyGem
  Name: hiredis
  Version: 0.4.1
  File: hiredis-0.4.1.gem
# устанавливаем
$ sudo gem install hiredis-0.4.1.gem
Building native extensions.  This could take a while...
Successfully installed hiredis-0.4.1
1 gem installed
Installing ri documentation for hiredis-0.4.1...
Installing RDoc documentation for hiredis-0.4.1...</pre>
<p>Теперь внимательно читаем porters handbook, делаем порт и далее действуем по правилам.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2011/11/06/gem-hiredis-freebsd.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Как я однажды тупил два дня на ровном месте</title>
		<link>http://binsh.ru/2011/10/18/dst.html</link>
		<comments>http://binsh.ru/2011/10/18/dst.html#comments</comments>
		<pubDate>Tue, 18 Oct 2011 09:17:45 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[лытдыбр]]></category>
		<category><![CDATA[рабочие будни]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=515</guid>
		<description><![CDATA[<p>В преддверии первой годовщины последнего осеннего перевода часов в России вспомнился один факап трехлетней давности (начало 2008 года). Я тогда занимался починкой  статистики посещаемости на одном региональном сайтике, который я поддерживал по дружбе.</p>
<p>У них было два сервера, один в интернете показывал контент посетителям, а второй располагался в офисе и содержал интерфейс администрирования сайта. Все хозяйство работало под FreeBSD 6.1 на очень стареньких машинах, на основном сервере  был Pentium 3 и 384 мегабайта памяти (однако много лет назад о такой конфигурации <a href="http://www.lib.ru/WEBMASTER/wwwhard.txt#4">можно было лишь помечтать</a>). Apache 2.2.2 вёл лог посещений в режиме &laquo;combined&raquo;, а по ночам всё накопленное за последние сутки обрабатывалось штатной программкой <a href="http://httpd.apache.org/docs/2.2/programs/logresolve.html">logresolve</a> (преобразовывает IP-адреса посетителей в имена хостов) и копировалось в отдельный файл resolved.log. Затем офисный сервер забирал получившийся файл по HTTP (в целях безопасности все &laquo;альтернативные&raquo; способы обмена файлами решили не использовать) и парсил его awstats&#8217;ом. Такая вот нехитрая схемка. Но проработала она ровно два месяца до середины декабря 2006 года и перестала.<br />
<!--more--><br />
Кроме нескольких программных ошибок обнаружилось еще пара стратегических провалов. Во-первых, офисный сервер иногда отключался из-за проблем с электричеством, и лог не забирался вовремя, а на следующий день просто дополнялся; после двух-трёх пропущенных дней файл с логами разросся до таких размеров, что даже в сжатом виде слишком долго передавался бы по http, и забирающий скрипт просто отваливался по таймауту. Во-вторых, установленный там logresolve натурально портил логи: читал из строки первые 1024 байта, обрабатывал IP-адрес и печатал их в STDOUT, завершив переводом строки; затем читались следующие 1024 байта и т.д. В результате строки, содержащие, например, длинные реферрерские URL, оказались разбитыми на несколько строк по 1024 байта каждая, что, возможно, не имело значения для awstats, но крайне затрудняло дополнительную обработку такого лога.</p>
<p>В итоге с декабря 2006 года лог-файл увеличился в размерах до полутора гигабайт. Я решил, что лучше его разбить на месяцы и скормить эти месяцы парсеру поочерёдно, однако сначала нужно было разобраться с лишними разрывами строк. Быстренько набросал однострочник на sed, который удаляет лишние переводы строк, если в третьем поле не содержится даты.</p>
<p>Однако несмотря на то, что на как на небольших, так и на довольно больших отрывках resolved.log данный скриптик отрабатывал относительно нормально, из реального лога читались только первые 170 мегабайт с копейками и скрипт надолго зависал. Решил, что, возможно, чего-то не учёл из-за малого опыта написания такого рода сценариев на sed, и переделал тот же самый алгоритм на perl и c  — безуспешно: после прочтения первых 170 мегабайт ничего не происходило.</p>
<pre>my $b='';
while(<>){
        chomp;
        if(/\[[0-9]+\/[a-zA-Z]+\/[0-9:]+\ \+0300\]/){
                print "$b\n";
                $b=$_;
        } else {
                $b.=$_
        }
}
print "$b\n";
</pre>
<p>Я несколько раз прогнал эти скрипты через valgrind с максимальными проверками утечек, избавился от некоторых ошибок, в конце концов перечитал кучу документации по freebsd на тему возможных ограничений на размер процесса в памяти (хотя больше восьми килобайт программа в памяти не занимала) и т.д. В общем, на два дня выпал из жизни, проводя это время в отладке&#8230; </p>
<p>В конце концов нашел причину моих мучений: в регулярном выражении, определявшем признак начала записи лога, была жестко прописана временная зона +0300, тогда как при переходе на летнее время она изменялась на +0400. Поэтому, когда цикл доходил до марта 2007 года, несколько сотен тысяч строк до следующего октября просто пропускались, а поскольку сервер был медленный, то на Ctrl+C и kill -TERM скрипты реагировали не сразу, и тем создавалось ощущение зависания.</p>
<p>После того, как я исправил этот регэксп, всё пошло как по маслу: скормил awstats&#8217;у старые логи, прикрутил logrotate, научил скрипты забирать статистику через scp; параллельно крону поставил <a href="http://sourceforge.net/projects/anacron">anacron</a>, благодаря чему забор и анализ логов стал производиться ежедневно вне зависимости от того, включен ли &laquo;офисный&raquo; сервер в 4 часа 15 минут утра. А потом и вовсе уговорил начальство поставить внешние счетчики. Теперь там стоит google analytics и все счастливы, а я немного прокачал скилл профайлинга.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2011/10/18/dst.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Комфортная работа в Midnight Commander</title>
		<link>http://binsh.ru/2011/09/08/mc.html</link>
		<comments>http://binsh.ru/2011/09/08/mc.html#comments</comments>
		<pubDate>Thu, 08 Sep 2011 13:28:49 +0000</pubDate>
		<dc:creator>bvk</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[mc]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=1026</guid>
		<description><![CDATA[<p>Многие мои коллеги принципиально игнорируют Midnight Commander, предпочитая работать в командной строке. Мотивируют это целым рядом причин, начиная с &laquo;нортон коммандер устарел еще в 1995 году&raquo; и заканчивая &laquo;я юниксоид с 1970 года и без всяких mc прекрасно управляюсь в консоли&raquo;. Конечно же, это дело вкуса, и можно (и нужно!) настроить консоль под себя так, чтобы она летала со скоростью мысли: на помощь приходят команда alias, сочетание Ctrl+R, описание команды shopt в builtins(1), пакет bash_completion или его аналоги, ряд мелких хаков, наподобие <a href="http://bappoy.pp.ru/2008/11/17/quick-call-ssh.html">такого</a>, или альтернатива в виде zsh, в конце концов.</p>
<p>Однако визуалам типа меня удобнее постоянно иметь перед глазами списки файлов и папок, а не помнить, какой файл где находится и что здесь есть еще. Кроме того, пользуясь исключительно командами <code>cd</code> и <code>ls --color</code>, можно легко проглядеть что-нибудь ненужное, типа оставшихся от vim бэкапов в текущем каталоге (если бэкапы нужны, см <code>:help backupdir</code>) или папок с именем из пробела. </p>
<p>Конечно, сначала mc производит немного гнетущее впечатление, но если разобраться и привыкнуть, то может оказаться, что даже с конфигурацией из коробки он очень облегчает жизнь разработчика и системного администратора. Поделюсь собственными хитростями, используемыми каждый день. За кадром осталось еще множество интересных фич, типа кастомной раскраски файлов в панели, смены цветовой схемы на черно-зеленую, сниппетов в редакторе mcedit, настраиваемых VFS, но поскольку я ими не пользуюсь, то ничего про них не скажу. Примеры их настроек и использования можно посмотреть в /etc/mc и в /usr/share/mc.</p>
<p>Сначала полезные мелочи, для многих очевидные.<br />
<!--more--></p>
<ul>
<li>Если до mc по каким-то причинам не доходят коды кнопок Fn, их можно заменить Esc-n. А Alt, иногда перехватываемый панелью меню, успешно заменяется кнопкой Esc
</li>
<li>Режим просмотра файлов «Full file list» лучше, чем «Short file list». При желании можно добавить туда показ прав на объекты файловой системы, например:
<pre>half type name | size | mtime | mode:3</pre>
</li>
<li>Панели подсказок над и под командной строкой внизу и меню сверху можно отключить в Options — Layout, будет больше пространства для списка файлов. Заодно там можно включить отображение свободного места в текущем разделе — очень полезно для нетбуков с мелкими экранами</li>
<li>При навигации по списку файлов сочетание <b>Ctrl+S</b> перекидывает на файл, начинающийся с вводимых символов</li>
<li><b>Alt+Y</b> перекидывает в предыдущую папку. Иногда это бывает полезно при восстановлении после ошибки «The shell is already running the command», за все время существования mc ставшей его визиткой</li>
<li>Встроенный редактор ужасен. В ~/.bashrc добавьте строчку <code>export EDITOR=vim</code>, а в пункте меню Options — Configuration снимите галку «Use internal editor». Точно так же можно использовать переменную окружения PAGER=view для просмотра файлов (опция «Use internal view»)</li>
<li><b>Alt+I</b> покажет текущую папку в противоположной панели, а <b>Alt+O</b> — папку под курсором, а если под курсором файл, то родительскую.</li>
<li>Начиная с ветки midnight commander 4.7.1, в меню сортировки появилась сортировка по версиям, она работает точно так же, как <code>ls -v</code>, т.е. показывает список 1.2.1, 1.2.2, 1.2.10 именно в этом порядке, а не в алфавитном (1.2.1, 1.2.10, 1.2.2). Сам делал :).</li>
<li><b>Ctrl+X c</b> — просмотр и редактирование прав на файл</li>
<li><b>Ctrl+X d</b> — три варианта сравнения двух каталогов: быстрое (по спискам файлов), по размерам (то же самое, только с учетом размеров), полное (по содержимому файлов)</li>
<li><b>Alt+C</b> — быстрый переход в нужную папку без изменения командной строки. По Esc-Tab показывает список подстановки (в командной строке mc Esc-Tab тоже иногда работает)</li>
<li>По <b>Ctrl+\</b> имеется многоуровневое меню быстрого доступа к папкам, в т.ч. и через FTP и SSH. При желании его можно отредактировать вручную в <b>~/.mc/hotlist</b></li>
</ul>
<p>На данный момент самой полезной фичей для меня является пользовательское меню.  Про него я уже писал пару раз (<a href="http://bappoy.pp.ru/2009/06/18/mc-tricks.html">1</a>, <a href="http://bappoy.pp.ru/2011/06/25/mc-unc-path.html">2</a>), сейчас расскажу более подробно.</p>
<p>Я поддерживаю несколько сайтов под mod_perl, и после изменений в коде startup.pl необходимо перезапускать процесс apache, свой для каждого сайта. Каждый сайт находится в /home/sites/sitename, а конфиг apache для этих сайтов — в /usr/local/apache/conf/httpd-sitename.conf.</p>
<p>Когда мне надоело вручную писать /usr/local/apache/bin/apachectl-sitename restart после каждого изменения, в ~/.mc/menu добавились строчки:</p>
<pre>s Restart apache for sitename
   sudo /usr/local/apache/bin/apachectl-sitename restart</pre>
<p>Первая строка задаёт быструю клавишу и название пункта меню, а все за ней следующее — команду, в которой можно использовать ряд макро-подстановок:</p>
<ul>
<li><b>%f</b> — имя файла под курсором, <b>%x</b> — расширение, <b>%b</b> — имя файла без расширения</li>
<li><b>%d</b> — каталог в активной панели, <b>%D</b> — каталог в неактивной панели
</li>
<li><b>%t</b> — выбранные файлы в активной панели, <b>%T</b> — в неактивной</li>
</ul>
<p>и т.д.</p>
<p>Потом появилось еще пять подобных пунктов, для каждого сайта. В конце концов, мне надоело выбирать стрелками нужную команду или искать в длинном списке, какая буква соответствует соответствует нужному пункту. Внимательно перечитав справку, появляющуюся при нажатии F1 в меню F2, добавил еще по строчке к каждому определению пункта меню:</p>
<pre>+= d /home/sites/sitename | f httpd-sitename.conf
s Restart apache for sitename
   sudo /usr/local/apache/bin/apachectl-sitename restart</pre>
<p>Первый символ &laquo;=&raquo; означает начало условия, при котором пункт меню становится активным по умолчанию (при вызове меню курсор уже стоит на этом пункте, так что остаётся только нажать Enter); если перед ним стоит +, то пункт появляется в меню только при выполнении этого условия. Следующий символ — тип условия, например:</p>
<ul>
<li><b>f шаблон</b> — имя файла соответствует шаблону (если в начале файла меню не указана опция shell_patterns=0, то под шаблоном имеется в виду шелл-шаблон, в противном случае — регулярное выражение)</li>
<li><b>d шаблон</b> — текущий каталог соответствует шаблону</li>
<li><b>t type</b> — то, что под курсором, имеет тип:
<ul>
<li>n не является директорией</li>
<li>r обычный файл</li>
<li>d каталог</li>
<li>l ссылка</li>
<li>c последовательное устройство</li>
<li>b блочное устройство</li>
<li>f FIFO</li>
<li>s сокет</li>
<li>x исполняемый файл</li>
<li>t отмеченный файл</li>
</ul>
<p>Различные типы можно комбинировать, например, <code>t rdl</code> означает файл, каталог или ссылку</li>
<li>остальные тесты можно подсмотреть в упомянутой справке</li>
</ul>
<p>Условия можно комбинировать и объединять, например:</p>
<pre>
# если находимся в папке /home/sites/sitename и под курсором — файл .sql, показать этот пункт меню
+= d /home/sites/site_name &amp; f *.sql
S import sql-file to database sitedb
   mysql sitedb &lt; %f
</pre>
<p>Таким образом, приведенный  ранее кусок означает &laquo;если находимся в каталоге сайта или стоим на конфигурационном файле apache для него, показать команду перезапуска сервера и встать на нее курсором&raquo;. </p>
<p>Остальное — дело фантазии и техники. Достаточно подумать о том, какие рутинные действия выполняются достаточно часто, и просто автоматизировать их.</p>
]]></description>
		<wfw:commentRss>http://binsh.ru/2011/09/08/mc.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
