<?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>Bappoy&#039;s blog &#187; linux</title>
	<atom:link href="http://bappoy.pp.ru/tag/linux/feed" rel="self" type="application/rss+xml" />
	<link>http://bappoy.pp.ru</link>
	<description>Линуксоид на велосипеде с моторчиком</description>
	<lastBuildDate>Mon, 06 Sep 2010 14:00:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Следующий месяц в GNU date</title>
		<link>http://bappoy.pp.ru/2010/08/31/date-next-month.html</link>
		<comments>http://bappoy.pp.ru/2010/08/31/date-next-month.html#comments</comments>
		<pubDate>Tue, 31 Aug 2010 11:37:44 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[pitfalls]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=971</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F08%2F31%2Fdate-next-month.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F08%2F31%2Fdate-next-month.html" height="61" width="51" /></a></div><p>Если 31 августа спросить у GNU date, какой будет следующий месяц, результат будет немного странным:</p>
<pre>$ date
Tue Aug 31 11:32:35 UTC 2010
$ date +"%Y-%m" --date "next month"
2010-10
$ date +"%Y-%m" --date "next month"
2010-10</pre>
<p>Документация GNU date (см <code>info date Relative items in date strings</code>) специально обращает внимание на эту проблему и рекомендует вычислять следующий месяц не для сегодняшнего числа, а для 15 числа текущего месяца:</p>
<pre>$ date +"%Y-%m" --date "$(date +%Y-%m-15) next month"
2010-09</pre>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2010/08/31/date-next-month.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Извлечение данных из виртуальных дисков VirtualBox</title>
		<link>http://bappoy.pp.ru/2010/07/21/mount-fs-from-vdi.html</link>
		<comments>http://bappoy.pp.ru/2010/07/21/mount-fs-from-vdi.html#comments</comments>
		<pubDate>Wed, 21 Jul 2010 15:51:42 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[fs]]></category>
		<category><![CDATA[mount]]></category>
		<category><![CDATA[virtualbox]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=940</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F07%2F21%2Fmount-fs-from-vdi.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F07%2F21%2Fmount-fs-from-vdi.html" height="61" width="51" /></a></div><p>Однажды глубокой ночью мне позарез понадобилось вытащить из остановленной виртуальной машины Virtualbox, находящейся на моем рабочем компьютере, один файлик. Удаленно запустить виртуальную машину и тем более подключиться к ней не получилось, поэтому я решил попробовать вытащить нужный раздел из vdi и смонтировать его. Ситуация немного осложнялась тем, что виртуальный жесткий диск хоть и содержал всего один корневой раздел, но был динамически расширяющимся, а это значит, что блоки файловой системы располагались в хронологическом порядке, а не в том, который ожидает драйвер файловой системы.</p>
<p>К счастью, можно легко преобразовать vdi из динамического формата в статический с помощью многоцелевой утилиты vboxmanage, входящей в состав пакета virtualbox:</p>
<pre>vboxmanage clonehd --variant static debian.vdi temp.vdi</pre>
<p>Теперь у нас есть файл temp.vdi, внутри которого где-то присутствует образ искомой файловой системы; для ее корректного извлечения нужно вычислить смещение образа относительно начала файла. В половине найденных по запросу &laquo;mount vdi linux&raquo; статей рекомендуется использовать для этих целей утилиту vditool, предназначенную на самом деле для внутреннего тестирования функциональности виртуальных дисков в VirtualBox. Раньше бинарник vditool можно было отдельно скачать с сайта virtualbox.org, но теперь его там по понятным причинам нет (желающие могут скомпилировать его самостоятельно: <a href="http://www.virtualbox.org/browser/trunk/src/VBox/Devices/Storage/testcase/vditool.cpp">vditool.cpp</a>) </p>
<p>Мы, как всегда, пойдем другим путем и воспользуемся подручными средствами. Первые 512 байт нашего vdi-файла — его заголовок, в котором можно разобраться, воспользовавшись, например, <a href="http://forums.virtualbox.org/viewtopic.php?p=29267&#038;sid=f13e432626fbf4b62807f7eb6fde8345#p292678">этим мануалом</a> или непосредственно описанием <a href="http://www.virtualbox.org/browser/trunk/src/VBox/Devices/Storage/VDICore.h#L135">структуры заголовка vdi</a> в исходниках VirtualBox. Из этих источников следует, что образ размечен следующим образом:<br />
512 байт: заголовок<br />
4 * N + X: карта мегабайтных блоков, здесь N ­— количество мегабайт в виртуальном жестком диске, а X — выравнивание получившегося числа до ближайшей верхней 512-байтной границы<br />
512 + 4*N + выравнивание: смещение данных</p>
<p>Зная точный размер виртуального диска, можно легко вычислить смещение вручную:</p>
<pre>$ vboxmanage showhdinfo f8e0de05-1419-405d-92d9-8358dc1e6bec
VirtualBox Command Line Management Interface Version 3.0.8_OSE
(C) 2005-2009 Sun Microsystems, Inc.
All rights reserved.

UUID:                 f8e0de05-1419-405d-92d9-8358dc1e6bec
Accessible:           yes
Description:
Logical size:         4095 MBytes
Current size on disk: 2637 MBytes
Type:                 normal (base)
Storage format:       VDI
In use by VMs:        debian (UUID: f1f8221a-6542-4dfe-9062-5397f429da4b)
Location:             /home/bvk/.VirtualBox/HardDisks/debian.vdi
</pre>
<p>(UUID нужного диска можно узнать из вывода команды vboxmanage list hhds). Здесь выравненное до 512 значение размера карты блоков равно 16384, а смещение данных — 16896.<br />
А можно и вытащить смещение непосредственно из заголовка vdi. Например, вот начало моего четырёхгигового виртуального диска:</p>
<pre>$ head -c 512 temp.vdi |hexdump  -C
00000000  3c 3c 3c 20 53 75 6e 20  56 69 72 74 75 61 6c 42  |&lt; &lt;&lt; Sun VirtualB|
00000010  6f 78 20 44 69 73 6b 20  49 6d 61 67 65 20 3e 3e  |ox Disk Image &gt;&gt;|
00000020  3e 0a 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |&gt;...............|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  7f 10 da be 01 00 01 00  80 01 00 00 02 00 00 00  |................|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000150  00 00 00 00 00 02 00 00  <b>00 42 00 00</b> 00 00 00 00  |.........B......|
00000160  00 00 00 00 00 00 00 00  00 02 00 00 00 00 00 00  |................|
00000170  00 00 f0 ff 00 00 00 00  00 00 10 00 00 00 00 00  |................|
00000180  ff 0f 00 00 ff 0f 00 00  db fa c4 c9 fd 13 ea 49  |...............I|
00000190  9e ae 4e 47 43 3f a0 3c  46 37 6c be e6 fd 02 40  |..NGC?.&lt;f7l ....@|
000001a0  a7 63 44 3f 6e 3f 26 d8  00 00 00 00 00 00 00 00  |.cD?n?&amp;.........|
000001b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001c0  00 00 00 00 00 00 00 00  0a 02 00 00 ff 00 00 00  |................|
000001d0  3f 00 00 00 00 02 00 00  00 00 00 00 00 00 00 00  |?...............|
000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000200</pre>
<p>Жирным шрифтом выделены необходимые четыре байта offsetData по смещению 0&#215;0158. Можно искать их визуально, помня о little-endian-порядке байт (в этом случае искомое значение равно 0&#215;00004200), а можно воспользоваться простенькой командой:</p>
<pre>$ head -c 348 temp.vdi |tail -c 4|perl -ne 'print unpack("L",$_),"\n"'
16896</pre>
<p>В любом случае, лишний раз перепроверить себя никогда не помешает.</p>
<p>Посмотрим, что находится по этому смещению. Сразу можно предположить, что там располагается начало образа жесткого диска, из этого следует, что первые 512 байт содержат mbr. Проверим:</p>
<pre>$ dd if=temp.vdi bs=512 count=1 skip=$((16896/512))|file -
1+0 records in
1+0 records out
512 bytes (512 B) copied, 3.9397e-05 s, 13.0 MB/s
/dev/stdin: x86 boot sector; partition 1: ID=0x83, active, starthead 1,
startsector 63, 7903917 sectors; partition 2: ID=0x5, starthead 0, startsector
7903980, 481950 sectors, code offset 0x4c</pre>
<p>Жесткий диск содержит 2 раздела: основной размером 3859 мегабайт, начинающийся с 63 сектора (1 сектор — 512 байт), и расширенный 235 мегабайт, отведенный установщиком Debian под swap (вот это сюрприз на виртуалке). Для очистки совести проверяем заголовок первого раздела:</p>
<pre>$ dd if=temp.vdi bs=512 count=3 skip=$((16896/512+63))|file -
3+0 records in
3+0 records out
1536 bytes (1.5 kB) copied, 4.7716e-05 s, 32.2 MB/s
/dev/stdin: Linux rev 1.0 ext3 filesystem data,
UUID=5ac94027-bf6e-43bc-9c3e-8a7830fe4ff8 (needs journal recovery) (large files)</pre>
<p>То, что надо! Осталось смонтировать. Несколько лет назад пришлось бы дополнительно извлекать все 7903917 секторов в отдельный файл и монтировать его, но сейчас можно просто указать смещение от начала файла как опцию mount (оставшиеся расширенный раздел и swap внутри него будут проигнорированы):</p>
<pre>$ sudo mount -o loop,offset=$((16896+63*512)) temp.vdi mnt
$ ls mnt/
bin   cdrom  etc   initrd.img      lib         media  opt   root  selinux  sys  usr  vmlinuz
boot  dev    home  initrd.img.old  lost+found  mnt    proc  sbin  srv      tmp  var  vmlinuz.old</pre>
<p>Задача решена, все свободны.</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2010/07/21/mount-fs-from-vdi.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Линус Торвальдс о Eee PC</title>
		<link>http://bappoy.pp.ru/2010/01/29/linus-about-eeepc.html</link>
		<comments>http://bappoy.pp.ru/2010/01/29/linus-about-eeepc.html#comments</comments>
		<pubDate>Fri, 29 Jan 2010 11:49:40 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[asus eee pc]]></category>
		<category><![CDATA[hardware]]></category>
		<category><![CDATA[linus]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=915</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F01%2F29%2Flinus-about-eeepc.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F01%2F29%2Flinus-about-eeepc.html" height="61" width="51" /></a></div><p>В предыдущем посте — <a href="http://bappoy.pp.ru/2010/01/29/linus-about-embroidery.html">небольшая история</a> о том, как в Linux была улучшена поддержка устройств экстра-маленького размера благодаря покупки Линусом Торвальдсом вышивальной машинки :) В <a href="http://article.gmane.org/gmane.linux.utilities.util-linux-ng/2888">письме Линуса</a> в рассылку util-linux-ng@kernel.org было упомянуто, что для управления этой машинкой он использует Eee PC с Fedora 12 на борту. Как <a href="http://bappoy.pp.ru/2008/05/06/eee-first-impressions.html">пользователь Eee PC 701g</a> с почти двухлетним стажем, я заинтересовался и написал Линусу письмо с несколькими вопросами о его опыте использования этих компьютеров. Получилось мини-интервью, которое и предлагается вашему вниманию.</p>
<p><strong>Q: Какие модели Eee PC Вы используете?</strong><br />
A: У меня их две штуки: 701 и 901.</p>
<p>Q: Это основной компьютер или один из дополнительных?<br />
A: Нет, конечно же, это не основной компьютер. Atom тормозной как грех. Я считаю, что процессоры с прямым выполнением команд (in-order execution) — преступление против человечности, и я уверен в том, что если Intel не предпримет значительных шагов (т.е. сделает Atom <a href="http://en.wikipedia.org/wiki/Out-of-order_execution">out-of-order</a>), ARM Cortex A9 захватит рынок low-end машин.</p>
<p>У меня есть пара нетбуков, потому что я люблю маленькие компьютеры и использую их в поездках. Но они никогда не могли бы служить основными машинами для разработки или чем-то вроде этого.</p>
<p>701 слишком мелкий для того, чтобы быть полезным. Экран крошечный и у него непозволительно маленькое разрешение. Клавиатуру едва можно использовать. 901 намного лучше и мог бы быть неплохим помощником в поездках, но разрешение тоже слишком маленькое (9 дюймов нормально, но 1024&#215;600 юзабельно только для смартфонов, а для лэптопов подошло бы как минимум 1366&#215;768, как мне кажется)</p>
<p>Поэтому я не использую ни один из них ни для чего, кроме тестирования. 901 используется моей женой для её вышивальной машинки, и для такого, обычного использования он подходит очень хорошо.</p>
<p>ВНИМАНИЕ! Наверно, следует заметить, что мои требования могут быть завышенными по сравнению с требованиями многих других людей. Моя основная машина — Nehalem 3.2 GHz c 6 GB RAM и двумя быстрыми SSD-дисками от Intel. Поэтому мои представления о том, какая производительность может считаться &laquo;приемлемой&raquo;, могут не совпадать с представлениями других.</p>
<p><strong>Q: какие задачи Eee PC помогает Вам выполнять?</strong><br />
A: Сейчас 701 работает тестовым стендом для совершенно различных вещей — я держу его поблизости в основном как  32-битный x86-стенд (все мои основные машины — x86-64, поэтому, если мне нужно проверить, что 32 бита еще работают, я использую 701).</p>
<p>901 я иногда использовал в поездках как лэптоп, и в основном он меня удовлетворял, но, откровенно говоря, существуют нормальные ноутбуки, которые намного-намного-намного лучше.</p>
<p>Например, я немного поигрался с машинами, основанными на CULV Core 2 Duo (вместо Atom) с экраном 1366&#215;768 и внезапно обнаружил, что может быть намного более мощная <em>(чем eeepc — прим.пер.)</em> сборка. Она больше по размерам (10 дюймов), потребляет больше энергии, но оно того стоит.</p>
<p><strong>Q: приобрели ли Вы эти нетбуки самостоятельно или они были подарены?</strong><br />
A: Оба Eee PC были подарены. 10&#8243; CULV Core2 было самым достойным приобретением, на которое я потратил свои деньги.</p>
<p><strong>Q: сколько времени Вы проводите перед этим нетбуком? Достаточен ли его размер для Вас?</strong><br />
A: См. выше. 701 и близко не стоял. 901 вполне пригоден к использованию, и если бы у него не было такое маленькое разрешение, он мог бы быть неплохим помощником в путешествиях.</p>
<p><strong>Q: производились ли какие-нибудь аппаратные модификации?</strong><br />
A: в оба добавил памяти, вроде сейчас в обоих по 2 Гб (возможно, 701 был с 512 мегабайтами, и я проапгрейдил до гигабайта, слишком лениво проверять). И еще в оба добавил ПЗУ: в 701 — быструю SD-карточку (понятие &laquo;быстрая&raquo; тут весьма относительно, но для SD-карточки неплохой результат), в 901 — Mini-PCI SSD.</p>
<p>Мне нравятся high-end SSD (например, <a href="http://torvalds-family.blogspot.com/2008/10/so-i-got-one-of-new-intel-ssds.html">интеловские замены жестким дискам</a>), но те, что используются в low-end нетбуках, страдают от ужасающе отвратительной скорости записи. Поэтому SSD в этих нетбуках, как правило, медленнее, чем реальные диски.</p>
<p><strong>Q: и еще один, более общий вопрос. Как Ваше рабочее время распределено между кодированием и административной/политической/социальной деятельностью?</strong><br />
A: Сейчас кодирую очень мало. Практически всё время занято обсуждениями с другими разработчиками и внесением их изменений в ядро.</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2010/01/29/linus-about-eeepc.html/feed</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Линус Торвальдс о машинках для вышивания</title>
		<link>http://bappoy.pp.ru/2010/01/29/linus-about-embroidery.html</link>
		<comments>http://bappoy.pp.ru/2010/01/29/linus-about-embroidery.html#comments</comments>
		<pubDate>Fri, 29 Jan 2010 06:11:48 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[linus]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=908</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F01%2F29%2Flinus-about-embroidery.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F01%2F29%2Flinus-about-embroidery.html" height="61" width="51" /></a></div><p><b>Часть первая.</b><br />
На Рождество Санта Клаус подарил Туве Торвальдс  машинку для вышивания. Среди прочих достоинств эта машинка имеет USB-интерфейс, по которому можно закачивать заранее приобретённые шаблоны вышивки в специальном закрытом формате. При подключении к компьютеру это чудо техники через минуту определяется как USB mass storage с файловой системой FAT12,  при этом закачивание небольших файлов происходит очень долго и зачастую не приводит ни к каким результатам: о возникающих ошибках пользователю ничего не сообщается. Таково всё проприетарное ПО, — <a href="http://torvalds-family.blogspot.com/2010/01/embroidery-gaah.html">сетует</a> Линус, — закрытые форматы, кривые прошивки, невнятные ошибки&#8230; Проблема предпросмотра шаблонов вышивок в формате PES на компьютере оказалась самой простой и теперь на git.kernel.org имеется специальная программа <a href="http://git.kernel.org/?p=linux/kernel/git/torvalds/pesconvert.git;a=summary">pesconvert</a> для обслуживания вышивальных машинок.</p>
<p><b>Часть вторая.</b><br />
Линус пишет <a href="http://thread.gmane.org/gmane.linux.utilities.util-linux-ng/2888">письмо</a> в рассылку util-linux-ng@vger.kernel.org с детальным описанием длительного процесса определения типов разделов и ФС на маленьком, медленном и подглючивающем блочном устройстве. После активного обсуждения (которое, несмотря на явную гиковость, можно читать как захватывающий детектив) было найдено несколько узких мест в  утилите blkid, пытающейся определить более чем 50 типов файловых систем по их сигнатурам, что приводит к неоднократному чтению 69 килобайт с устройства, и в сумме объём прочитанных данных, с учётом упреждающего чтения, составляет около половины объёма всего устройства. Учитывая тот факт, что скорость обмена данными у этой штуки составляет 16  килобайт в секунду, простое определение единственного fat-раздела занимает около 30 секунд (всё это нужно для того, чтобы udev смог корректно примонтировать это устройство).</p>
<p>Совместными усилиями задержка была сведена к рекордному минимуму в полсекунды. Для этого Karel Zak (главный мейнтейнер util-linux-ng) добавил в blkid несколько опций, ограничивающих количество возможных ФС и объём читаемых данных для очень маленьких устройств (зачем пытаться определить raid на диске размером с полдискеты?), Линус немного оптимизировал кое-какие системные вызовы и теперь в ближайшем выпуске util-linux-ng будет заявлена поддержка очень маленьких дисков, а в ядре Linux, чем черт не шутит — частичная поддержка неких вышивальных машинок.</p>
<p>Часть третья последует, не пропустите.</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2010/01/29/linus-about-embroidery.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Несколько ссылок по истории computer science</title>
		<link>http://bappoy.pp.ru/2010/01/25/computer-sciense-history.html</link>
		<comments>http://bappoy.pp.ru/2010/01/25/computer-sciense-history.html#comments</comments>
		<pubDate>Mon, 25 Jan 2010 12:06:44 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[history]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=847</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F01%2F25%2Fcomputer-sciense-history.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F01%2F25%2Fcomputer-sciense-history.html" height="61" width="51" /></a></div><p>Несколько месяцев назад заинтересовался причинами появления управляющих кодов ASCII в их нынешнем виде. Раскопки привели меня к первым терминалам в Multics, терминалы — к телетайпам, телетайпы — к телеграфным аппаратам. Тема чрезвычайно интересная, но полноценного поста у меня так и не вышло по разным причинам. Просто накидаю сюда ссылок для интересующихся (в основном на английском).</p>
<p><b>Unix и его предшественники</b><br />
<a href="http://www.multicians.org/">Multicians.org</a> — один из основных сайтов по предыстории Unix. В основном описывает различные аспекты ОС Multics (включая <a href="http://archive.computerhistory.org/resources/text/Honeywell/Honeywell.MulticsSystem.1975.102646162.pdf">рекламную брошюру</a> (4 Мб)), но содержит также массу сведений и о ранних вариантах <a href="http://www.multicians.org/unix.html">Unix</a>, и о <a href="http://www.multicians.org/thvv/7094.html">CTSS</a>.</p>
<p><a href="http://www.levenez.com/unix/">Unix history</a> — основной сайт по истории Unix.</p>
<p>Концепция иерархической файловой системы <a href="http://www.multicians.org/features.html#tag1.1">впервые</a> была <a href="http://www.multicians.org/fjcc4.html">описана</a> в 1965 году и сильно отличалась от ныне используемой. В частности, в качестве разделителя каталогово предлагалось использовать двоеточие, а на уровень выше можно было  ссылаться как на <code>*</code>; у каждого файла присутствовал специальный атрибут TRAP, в котором можно было указать свою процедуру проверки прав доступа к этому файлу. Но уже в Multics реализация файловой системы значительно отличалась от данного проекта иной, а в Unix и вовсе приняла привычный нам вид.</p>
<p><a href="http://cm.bell-labs.com/cm/cs/who/dmr/hist.html">The Evolution of the Unix Time-sharing System</a> (Dennis M. Ritchie, 1979) — краткая история Unix, рассказанная одним из её создателей.</p>
<p><a href="https://www.usenix.org/events/usenix09/tech/full_papers/toomey/toomey.pdf">The Restoration of Early UNIX Artifacts</a> — опыт восстановления файлов с древней ленты, содержащей один из самых первых релизов Unix. В конце документа несколько интересных ссылок.</p>
<p><a href="http://www.bitsavers.org/pdf/bellLabs/unix/PreliminaryUnixImplementationDocument_Jun72.pdf">Исходный код Unix</a> — отсканированная распечатка тщательно прокомментированных ассемблерных кодов  Unix. Датируется 1972 годом. 11 мегабайт.</p>
<p><a href="http://74.125.77.132/search?q=cache:l4ZThOZLuR0J:searchenterpriselinux.techtarget.com/tip/0,289483,sid39_gci1098161,00.html+http://searchenterpriselinux.techtarget.com/tip/0,289483,sid39_gci1098161,00.html&#038;cd=1&#038;hl=en&#038;ct=clnk">Excavating ancient abbreviations in Linux</a> ­— история происхождения некоторых аббревиатур, используемых в UNIX/Linux (для чтения <a href="http://searchenterpriselinux.techtarget.com/tip/0,289483,sid39_gci1098161,00.html">оригинала</a> требуется<br />
регистрация, поэтому ссылка на кэш гугла).</p>
<p>Буду благодарен за PDF/DJVU версию книги &laquo;A quarter century of Unix&raquo; by Peter Salus :)</p>
<p><b>Терминалы</b><br />
<a href="http://www.cs.utk.edu/~shuford/terminal/">Коллекция информации о текстовых терминалах</a>, отправная точка исследований.</p>
<p><a href="http://www.multicians.org/terminals.html">Рассказ одного из создателей Multics о первых терминалах</a> и опыте удалённой домашней работы (70-е годы, суперкрутые модемы на 1200 бод) (en)</p>
<p><a href="http://vt100.net/vt_history">Краткая история терминалов DEC (в т.ч. VT100)</a></p>
<p><a href="http://foldoc.org/smart+terminal">Что такое &laquo;smart terminal&raquo;</a> и чем он отличается от &laquo;dumb terminal&raquo;. В<br />
основном тем, что умеет проверять пользовательский ввод уже на стороне терминала, а не передаёт его серверу.</p>
<p><b>Телеграф</b><br />
<a href="http://www.qrz.ru/articles/article243.html">К вопросу о возникновении телеграфа</a> множество интересных сведений из истории телеграфной связи</p>
<p><a href="http://www.3dnews.ru/editorial/razgovor_tekstom/">История телеграфа в России</a></p>
<p><a href="http://www.amyat.narod.ru/theory/goloveshkin_murashkin_telegrafnoe_delo/index.htm">Телеграфное дело. Пособие для сержантов и старших специалистов войск связи</a> — раритет :) Книжка 1946 года выпуска, доступно и понятно описывает теорию электротехники и электроники по состоянию на момент окончания Великой Отечественной войны, а также знакомит читателя с основными понятиями телеграфной связи.</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2010/01/25/computer-sciense-history.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Шпаргалка по созданию chroot-окружения в Debian средствами debootstrap</title>
		<link>http://bappoy.pp.ru/2010/01/20/debian-chroot.html</link>
		<comments>http://bappoy.pp.ru/2010/01/20/debian-chroot.html#comments</comments>
		<pubDate>Wed, 20 Jan 2010 10:49:45 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[chroot]]></category>
		<category><![CDATA[debian]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=845</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F01%2F20%2Fdebian-chroot.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F01%2F20%2Fdebian-chroot.html" height="61" width="51" /></a></div><p>Для тестирования различных версий нашего продукта (внутри — БД под управлением mysql и интерфейс к ней на PHP под Apache2)  требуется быстро создавать многочисленные chroot-окружения на выделенном сервере и управляться с ними. </p>
<p>В базовой системе (lenny) оставляем только функционал, необходимый для управления всем хозяйством, лично мне необходимы mc, openssh, vim, bash_completion и иногда svn. Также неплохо поиметь где-нибудь (да хоть на этой же машине) кэширующий прокси для репозиториев debian, типа <a href="http://apt-proxy.sourceforge.net/">apt-proxy</a> или <a href="http://www.nick-andrew.net/projects/apt-cacher/">apt-cacher</a>, чтобы не создавать излишнюю нагрузку на региональные зеркала. У нас используется apt-cacher, работающий по адресу http://apt:3142.</p>
<p><a href="http://wiki.debian.org/Debootstrap">Debootstrap</a> ­— основная рабочая лошадка:</p>
<pre>apt-get install debootstrap</pre>
<pre>debootstrap --include=mc,ssh,vim lenny /systems/lenny http://apt:3142/ftp.debian.org/debian/</pre>
<p>Первый аргумент — название релиза, второй — путь, куда устанавливается система, третий — адрес репозитория. В опции &#8211;include через запятую указываются пакеты, которые необходимы, но не входят в минимальную базовую систему. Debootstrap выкачивает из репозитория и устанавливает минимальный набор пакетов, теоретически сразу после этого можно делать chroot /systems/lenny и переходить к работе, но осталась еще несколько немаловажных доделок:</p>
<p>Добавляем идентификатор системы, который будет отображаться в скобках в приглашении шелла (читай — bash), выполняемом в chroot-окружении:</p>
<pre>echo lenny > /systems/lenny/etc/debian_chroot</pre>
<p>Но работа в основном ведется от имени root, а в squeeze и sid у root&#8217;а в .bashrc переменная окружения PS1 переопределяется и этот идентификатор пропадает. Поэтому если делаем виртуалку squeeze, то строчку с PS1 в /root/.bashrc лучше закомментировать:</p>
<pre>sed -i 's/^\(export PS1.*\)$/#\1/g' /systems/<b><font color="red">squeeze</font></b>/root/.bashrc</pre>
<p>Монтируем /dev/pts — виртуальную файловую систему, которая динамически создаёт файлы терминалов /dev/pts/X для каждого нового подключения; это необходимо для нормального функционирования многих программ, работающих с терминалом, в т.ч. скриптов postinst и config пакета mysql-server:</p>
<pre>mount -t devpts devpts /systems/lenny/dev/pts</pre>
<p>Монтируем /proc (реально proc в новом месте будет содержать ту же информацию, что и общесистемный /proc):</p>
<pre>mount -t proc proc /systems/lenny/proc</pre>
<p>Чтобы apt-get не ругался на неподписанные пакеты при установке, необходимо обновить файл Release.gpg, т.к. по умолчанию debootstrap его не устанавливает. Это проще всего сделать обновлением индексных файлов репозитория:</p>
<pre>chroot /systems/lenny apt-get update</pre>
<p>После этого уже можно делать <code>chroot /systems/lenny</code>, устанавливать и настраивать пакеты, запускать/останавливать сервисы и т.д. Главная проблема при этом ­— следить за тем, чтобы сервисы в разных chroot&#8217;ах не конфликтовали, пытаясь занять порт на одном IP-адресе. Обычно добавляются виртуальные сетевые интерфейсы и им назначаются виртуальные же IP-адреса, которые и указываются в настройках сервисов.</p>
<p>Disclaimer: данная заметка описывает мой персональный опыт и не претендует на полноту. Комментарии и дополнения приветствуются.</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2010/01/20/debian-chroot.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Как не пропустить момент установки нового ядра с помощью команды watch</title>
		<link>http://bappoy.pp.ru/2010/01/13/watch.html</link>
		<comments>http://bappoy.pp.ru/2010/01/13/watch.html#comments</comments>
		<pubDate>Wed, 13 Jan 2010 16:52:33 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[humor]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=886</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F01%2F13%2Fwatch.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2010%2F01%2F13%2Fwatch.html" height="61" width="51" /></a></div><p>Выдержка из <code>man 1 watch</code> (входит в комплект утилит procps в Debian Lenny):</p>
<pre>You can watch for your administrator to install the latest kernel with

        watch uname -r

(Note that <u>-p</u> isn’t guaranteed to work across reboots, especially
in the face of <b>ntpdate</b> or other bootup time-changing mechanisms)</pre>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2010/01/13/watch.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Разделение аргументов в shebang</title>
		<link>http://bappoy.pp.ru/2009/12/28/shebang-args.html</link>
		<comments>http://bappoy.pp.ru/2009/12/28/shebang-args.html#comments</comments>
		<pubDate>Sun, 27 Dec 2009 20:29:25 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[shebang]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=870</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F12%2F28%2Fshebang-args.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F12%2F28%2Fshebang-args.html" height="61" width="51" /></a></div><p>В <a href="http://bappoy.pp.ru/2008/12/29/bash-pitfalls-part05.html#comment-8577">комментариях</a> к прошлогоднему <a href="http://bappoy.pp.ru/tag/bash-pitfalls">переводу Bash Pitfalls</a> внимательный <b>flavi</b> задался вопросом, почему при попытке выполнить скрипт, в начале которого написано </p>
<pre>#!/bin/bash --posix --verbose</pre>
<p>выдаётся ошибка </p>
<pre>/bin/bash: --posix --verbose: invalid option</pre>
<p>в то время как в интерактивном режиме bash нормально запускается с такой комбинацией опций; более того, если в shebang&#8217;е оставить только одну из этих опций, то скрипт также запускается без ошибок.</p>
<p>Поначалу я предположил, что <code>--posix</code> запрещает    опции, не определённые <a href="http://www.opengroup.org/onlinepubs/009695399/utilities/sh.html">стандартом POSIX на sh</a>. Но тогда попытка выполнить <code>bash --posix --norc</code> также приводила бы к ошибке, и конструкция <code>#!/bin/bash --verbose --norc</code> работала бы нормально, а это не так.</p>
<p>Пришлось разбираться более плотно. В <code>bash (1)</code> я вычитал следующее (выделение — моё):</p>
<blockquote><p>If the program is a file beginning with #!, the remainder of the first line specifies an interpreter for the  program.  The shell executes the specified interpreter on operating systems that do not handle this  executable format themselves.  The arguments to the interpreter consist of a  <b>single</b><b>  optional  argument  following  the  interpreter  name on the first line of the program, followed by the name of the program, followed by the command arguments, if any.</b></p></blockquote>
<p>Т.е. в shebang можно задавать только один аргумент; кроме того, bash самостоятельно анализирует shebang и вызывает указанный интерпретатор только в случае, если система сама не может выполнить этот скрипт.</p>
<p>Сам файл передаётся на выполнение с помощью системного вызова <code>execve (2)</code> (это я вычитал в файле <code>execute_cmd.c</code> в исходном коде bash), в man-странице которого и разъясняется политика партии по поводу разбиения аргументов интерпретатора:</p>
<blockquote><p>On Linux, the entire string following the interpreter name is passed as a single argument  to  the  interpreter, and this string can include white space.</p></blockquote>
<p>Таким образом, в самом первом примере у bash в argv оказывается  не два аргумента <code>--verbose</code> и <code>--norc</code>, а  один <code>--verbose --norc</code>, что и приводит к ошибке, и вина bash лишь в том, что он не разбивает свои аргументы на части, как это делает, например, Perl.</p>
<p>Причина такого странного поведения операционной системы (казалось бы, что сложного в том, чтобы просто разбить строку на части по пробелам или символам табуляции) описана, например, <a href="http://lkml.indiana.edu/hypermail/linux/kernel/0812.0/02503.html">в этой дискуссии LKML</a> или, более подробно, в <a href="http://unix.derkeiler.com/Mailing-Lists/FreeBSD/arch/2005-02/0039.html">письме Garance A Drosihn</a> в рассылку freebsd-arch. Вкратце, если бы механизм механизм обработки shebang (в Linux — <a href="http://lxr.linux.no/#linux+v2.6.32/fs/binfmt_script.c">linux/fs/binfmt_script.c</a>) передавал все аргументы интерпретатору, то для некоторых из них было бы затруднительно отделить аругменты интерпретатора от собственно аргументов  вызываемого скрипта. По крайней мере, так было еще на заре развития Unix и с тех пор <a href="http://www.in-ulm.de/~mascheck/various/shebang/#results">большая часть Unix-систем</a> передаёт все аргументы как единую строку.</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2009/12/28/shebang-args.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Басни про git</title>
		<link>http://bappoy.pp.ru/2009/12/27/git.html</link>
		<comments>http://bappoy.pp.ru/2009/12/27/git.html#comments</comments>
		<pubDate>Sat, 26 Dec 2009 22:19:50 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/2009/12/27/%d0%b1%d0%b0%d1%81%d0%bd%d1%8f-%d0%bf%d1%80%d0%be-git.html</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F12%2F27%2Fgit.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F12%2F27%2Fgit.html" height="61" width="51" /></a></div><p>Пытающимся отвыкнуть от идеологии CVS и SVN —  <a href="http://hades.name/blog/2009/05/23/the-git-parable-ru/">рассказ о концепциях распределённых систем контроля версий</a>.</p>
<p><a href="http://los-t.livejournal.com/tag/git+guts">Более подробное введение</a></p>
<p><font size=small>ага, для ссылок есть твиттер и del.icio.us, но ЭТУ ссылку я уже однажды потерял. Так что пусть тут побудет, в назидание.</font></p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2009/12/27/git.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Заметки на память</title>
		<link>http://bappoy.pp.ru/2009/09/07/782.html</link>
		<comments>http://bappoy.pp.ru/2009/09/07/782.html#comments</comments>
		<pubDate>Mon, 07 Sep 2009 10:34:37 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[mount]]></category>
		<category><![CDATA[samba]]></category>
		<category><![CDATA[su]]></category>
		<category><![CDATA[sudo]]></category>
		<category><![CDATA[syslog]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=782</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F09%2F07%2F782.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F09%2F07%2F782.html" height="61" width="51" /></a></div><p>Если после перезагрузки не сохраняются параметры клавиатуры в Gnome-окружении Debian или Ubuntu, поможет добавление <strong>setxkbmap</strong> в приложения, запускаемые автоматически при входе в систему (&laquo;Система — Параметры — Запускаемые приложения&raquo; или &laquo;System — Parameters — Sessions&raquo;)</p>
<p>Если при монтировании расшаренного через Samba каталога через mount.cifs симлинки отображаются как локальные ссылки, нужно на обеих машинах в <strong>smb.conf</strong> отключить unix extensions, которые и отвечают за такое поведение символических ссылок:</p>
<pre>unix extensions = no</pre>
<p>Если в Ubuntu одновременно перестали работать su, sudo, входы в систему с консоли и через ssh (основной симптом: зависает после ввода пароля), то для постановки окончательного дифференциального диагноза можно попробовать выполнить команду &laquo;logger test&raquo;. Если и это зависает, то налицо проблема с демоном syslogd. В моем случае решение вылилось в отключении опции &laquo;<strong>-r</strong>&raquo; в<strong>/etc/default/syslogd</strong> (принимать сообщения по сети), которая однажды была добавлена мной для удаленной отладки одного voip-телефона. На самом деле это явная бага, которая, судя по <a href="https://bugs.launchpad.net/ubuntu/+source/sysklogd/+bug/26986">Ubuntu Bug 26986</a>, тянется аж с 2005 года.</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2009/09/07/782.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ссылка на определенное место в man&#8217;е</title>
		<link>http://bappoy.pp.ru/2009/08/24/reference-to-fragment-in-less.html</link>
		<comments>http://bappoy.pp.ru/2009/08/24/reference-to-fragment-in-less.html#comments</comments>
		<pubDate>Mon, 24 Aug 2009 10:04:53 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[less]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=773</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F08%2F24%2Freference-to-fragment-in-less.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F08%2F24%2Freference-to-fragment-in-less.html" height="61" width="51" /></a></div><p>В блоге <a href="http://linsovet.com/">&laquo;Полезные советы по Linux&raquo;</a> <a href="http://linsovet.com/zsh-vcs-info-in-prompt">наткнулся</a> на способ ссылаться на определенное место в документации:</p>
<pre>sh -c 'PAGER="less" LESS="-p search_string" man man_page'</pre>
<p>Явно вызываем sh, задаем просмотрщик less и указываем ему строку, которую нужно найти. Команда man запустит less и прокрутит экран до первого совпадения.</p>
<p>Конечно же, необходимо убедиться, что заданный шаблон присутствует в документе хотя бы один раз, и первый раз встречается именно в том месте, на которое вы хотите сослаться. Если ни одного совпадения не найдено, будет выведена ошибка и man будет показан с его начала, да и то только после нажатия Enter. Также стоит учитывать, что у адресата вашего сообщения может быть другой shell, другая версия документации и вообще другая операционная система.</p>
<p>Несколько примеров (предполагаем, что в качестве шелла используется sh-compatible shell типа bash или zsh, а переменная PAGER установлена в less).</p>
<p>Абзац в bash (1) про фичу <b>complete-into-braces</b> из одной из предыдущих заметок:</p>
<pre>LESS="-p complete-into-braces" man bash</pre>
<p>Раздел про подстановку из истории в bash (1). Поскольку строка HISTORY EXPANSION в документе встречается неоднократно, то требуется привязка к началу строки:</p>
<pre>LESS='-p ^s*HISTORY EXPANSION' man bash</pre>
<p>Подсветка важной фразы целиком:</p>
<pre>LESS='-p Please note.*log the command[^.]*.' man sudo</pre>
<p>Этот фокус можно задействовать в других утилитах, использующих less, например, в perldoc:</p>
<pre>LESS='-p ^s*Range Operators' perldoc perlop</pre>
<p>О том, как эта конструкция работает:</p>
<pre>LESS='-p MANPAGER, PAGER' man man
LESS='-p -ppattern.*' man less
LESS='-p Options which.*' man less</pre>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2009/08/24/reference-to-fragment-in-less.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Мелкие хитрости midnight commander</title>
		<link>http://bappoy.pp.ru/2009/06/18/mc-tricks.html</link>
		<comments>http://bappoy.pp.ru/2009/06/18/mc-tricks.html#comments</comments>
		<pubDate>Thu, 18 Jun 2009 17:12:20 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[diff]]></category>
		<category><![CDATA[mc]]></category>
		<category><![CDATA[vim]]></category>
		<category><![CDATA[vimdiff]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=708</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F06%2F18%2Fmc-tricks.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F06%2F18%2Fmc-tricks.html" height="61" width="51" /></a></div><p>Из /usr/share/doc/mc/README.Debian:<br />
- если в истории команд mc постоянно присутствуют строки вида <code>cd "`printf "%b" '\0057home'`"</code>, убедитесь, что в переменной окружения <code>HISTCONTROL</code> присутствует ignorespace или ignoreboth, или же эта переменная вообще отсутствует. Подробности в <a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=440102">debian bug 440102</a>.<br />
- действие, с незапамятных времен выполнявшееся по кнопкам M-O (в противоположной панели отобразить путь в текущей панели), с 4.6.2-pre1 пор переехало на M-I, а на M-O теперь отображение в другой панели родительского каталога, или каталога, находящегося под курсором. Эргономично, да, но очень непривычно. Кстати, русскоязычная справка, вызываемая по F1, описывает старое поведение. </p>
<hr />
У нас есть несколько папок с однотипными объектами вида 1.1.1.1, 1.1.1.2, &#8230;, 1.1.1.10, 1.1.1.11, &#8230;, 1.4.3.5, 1.4.3.9, 1.4.3.10 &#8230;. Опытные разработчики уже, наверно, догадались, к чему я клоню :) При обычной алфавитно-цифровой сортировке 1.1.1.10 следует после 1.1.1.1, но до 1.1.1.2, что очень неприятно. У GNU-версии ls есть специальная опция -v, которая как раз выводит файлы в порядке возрастания версий. А в mc ничего похожего, увы, нет.</p>
<p>За 10 минут сделал <a href="http://mc.redhat-club.org/cms/forum/viewthread.php?thread_id=146">патч</a>, добавляющий вариант &laquo;сортировать файлы по версии&raquo; в меню выбора режима сортировки. К сожалению, простой правкой конфига тут обойтись не получилось, поэтому пришлось пересобрать пакет mc целиком — еще 40 минут, но оно того стоило :-)</p>
<hr />Мегаполезной фичей вдруг оказалось пользовательское меню, которым я раньше почти никогда не пользовался (наверно, потому, что там ничего полезного не было — ну на кой мне &laquo;распаковать архив&raquo;, если я то же самое сделаю тремя привычными способами). Прочитав раздел справки про mc.menu и добавив в ~/.mc/menu несколько строчек, я сэкономил себе кучу времени, тратившегося на бесконечные  </p>
<pre>vimdiff Alt-A Alt-Enter Tab Alt-A Alt-Enter Enter</pre>
<p>и </p>
<pre>diff -rubB Alt-A  Tab Alt-A Enter</pre>
<p>Этот код добавляет в меню две команды: сравнения двух каталогов и мержа файла в одном каталоге с одноименным файлом в другом каталоге:</p>
<pre>d   Compare directories
    if [ "%d" = "%D" ]; then
      whiptail --msgbox "The two directores must be different" 7 60
      exit 1
    fi
    diff -rubB "%d" "%D" | vim -

# обычный непомеченный файл
+ t r &#038; ! t t
f   Diff &#038; merge file under cursor with the same file in other panel
    if [ "%d" = "%D" ]; then
        # если в противоположной панели открыта та же папка
        whiptail --msgbox "The two directores must be different" 7 60
      exit 1
    fi
    if [ ! -f "%D/%f" ] ; then
       # если в противоположной панели нет файла с таким же именем
        whiptail --msgbox "No copy of %f in %D" 7 60
        exit 1
    fi
    if diff -q "%D/%f" "%d/%f" ; then
       # если файлы не различаются
        whiptail --msgbox "%D/%f and %d/%f are identical" 10 80
        exit 1
    fi
    vimdiff "%d/%s" "%D"</pre>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2009/06/18/mc-tricks.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Рекурсивные операции с файлами в Linux</title>
		<link>http://bappoy.pp.ru/2009/06/16/recursive.html</link>
		<comments>http://bappoy.pp.ru/2009/06/16/recursive.html#comments</comments>
		<pubDate>Tue, 16 Jun 2009 04:30:21 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[chattr]]></category>
		<category><![CDATA[chgrp]]></category>
		<category><![CDATA[chmod]]></category>
		<category><![CDATA[chown]]></category>
		<category><![CDATA[cp]]></category>
		<category><![CDATA[grep]]></category>
		<category><![CDATA[ls]]></category>
		<category><![CDATA[rm]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=682</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F06%2F16%2Frecursive.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F06%2F16%2Frecursive.html" height="61" width="51" /></a></div><p>Иногда возникает путаница между опциями -r и -R, каждая из которых в разных программах может означать рекурсивную обработку файлов в найденных каталогах. А может означать нечто совершенно противоположное или работать не так, как этого ожидал пользователь. Попробуем разобраться, в каких случаях что используется.</p>
<h3>Эпиграф</h3>
<p><em>— Это новый &laquo;Гарри Поттер&raquo;. Я заказал версии для детей и взрослых, чтобы проверить, что в тексте нет различий.<br />Морис Мосс, The IT Crowd.</em></p>
<h3>chmod</h3>
<p>Неправильно: </p>
<pre>chmod -r 755 dir</pre>
<p>Ключ -r у chmod интерпретируется как &laquo;запретить всем чтение файла&raquo;, а 755 в данном случае рассматривается как название файла, у которого изменяются права. Поскольку в подавляющем большинстве случаев файла с таким названием в текущей директории отсутствует, то команда возвращает ошибку.</p>
<p>Правильно:</p>
<pre>chmod -R 755 dir</pre>
<h3>chown, chattr, chgrp</h3>
<p>Неправильно:</p>
<pre>chown -r user:group dir
chattr -r dir +I
chgrp -r group dir</pre>
<p>У вышеперечисленных команд опция -r просто отсутствует. Для рекурсивной обработки директорий необходимо использовать опцию -R. Очевидно, так сделано из солидарности с &laquo;братской&raquo; командой chmod</p>
<p>Правильно: </p>
<pre>chown -R user:group dir. .
chgrp -R group dir
chattr -R dir # только Linux, только для ext2/ext3</pre>
<h3>cp</h3>
<p>Неправильно:</p>
<pre>cp -r dir destdir</pre>
<p>Правильно:</p>
<pre>cp -R dir destdir</pre>
<p>Несмотря на то, что в странице документации cp из GNU coreutils сказано, что опции -r и -R равнозначны и означают рекурсивную обработку встречающихся директорий, опция -r, в отличие от -R, не соответствует <a href="http://www.opengroup.org/onlinepubs/000095399/utilities/cp.html">стандарту POSIX</a> и ее указание может повлечь за собой неожиданные последствия в случае, если очередной копируемый объект является чем-то отличным от обычного файла или директории (например, символической ссылкой, fifo или сокетом). В таких случаях некоторые реализации cp просто копируют содержимое ссылки/fifo, тогда как при -R такие объекты пересоздаются заново. Раньше такое поведение было присуще GNU cp, о чем до сих пор имеется свидетельство в <a href="http://www.opennet.ru/man.shtml?topic=cp&#038;category=1&#038;russian=0">русском man cp</a>. Что касается более правильных (чем Linux) систем, то, например, в BSD-версии cp опция -r работает в &laquo;режиме совместимости&raquo;, т.е. не создает символическую ссылку заново, а копирует содержимое в файл с тем же именем.</p>
<h3>ls</h3>
<p>Неправильно: </p>
<pre>ls -r</pre>
<p>Ключ -r команды ls означает &laquo;обратный порядок сортировки&raquo;<br />
Правильно: </p>
<pre>ls -R</pre>
<h3>rm, grep</h3>
<p>Зато в следующих случаях употребление -r/-R равнозначно:</p>
<pre>rm -r dir
rm -R dir</pre>
<p>а также</p>
<pre>grep -r pattern dir
grep -R pattern dir</pre>
<p>Что касается grep, то, во-первых, обе опции не соответствуют POSIX (но, похоже, присутствуют во всех реализациях) Во-вторых, иногда возникает путаница между опциями -i (игнорировать регистр) и -I (пропускать двоичные файлы). Но это уже тема для другого разговора :)</p>
<h3>Прочие команды</h3>
<p>Поскольку команд, в том или ином виде поддерживающих рекурсивную обработку каталогов, набралось довольно много, то я попробовал свести их в одну таблицу. </p>
<table border=0 width=90%>
<tr>
<th>команда</th>
<th>-r</th>
<th>-R</th>
</tr>
<tr valign=top>
<td>chacl</td>
<td><b>рекурсия</b></td>
<td>удаление ACL только с файлов</td>
</tr>
<tr valign=top>
<td>setfacl</td>
<td>не поддерживается</td>
<td><b>рекурсия</b></td>
</tr>
<tr valign=top>
<td>cvs</td>
<td>номер ревизии</td>
<td><b>рекурсия</b></td>
</tr>
<tr valign=top>
<td>diff</td>
<td><b>рекурсия</b></td>
<td>не поддерживается</td>
</tr>
<tr valign=top>
<td>gzip/gunzip</td>
<td><b>рекурсия</b></td>
<td>не поддерживается</td>
</tr>
<tr valign=top>
<td>zip</td>
<td><b>рекурсия</b></td>
<td>рекурсия, начиная с текущей директории (см. man zip, там есть существенная разница в обработке -r и -R) </td>
</tr>
<tr valign=top>
<td>rsync</td>
<td><b>рекурсия</b></td>
<td>использование относительных путей</td>
</tr>
<tr valign=top>
<td>wget</td>
<td><b>рекурсия</b></td>
<td>указывает список отвергаемых шаблонов</td>
</tr>
</table>
<h3>Заключение</h3>
<p>Как видно, в большинстве случаев для указания рекурсии используется опция -r в нижнем регистре, в противовес стандартным утилитам, для которых характерно все же -R. Поэтому совет один: в случае сомнения смотрите в man, там все написано :)</p>
<h3>Постскриптум</h3>
<p>По абзацу про cp видно, что русская документация в некоторых дистрибутивах (не будем показывать пальцем на Debian и Ubuntu) не соответствует реальному положению дел. В частности, несмотря на то, что в jaunty используется GNU coreutis 6.10, русский man описывает cp версии 4.1. Желающие могут самостоятельно сравнить свою версию man 1 cp с <a href="http://www.opennet.ru/man.shtml?topic=cp&#038;category=1&#038;russian=0">локализованной</a>. Другими словами, русская страница документации cp в силу своей древности вводит пользователя в заблуждение, т.е. врёт. По этой причине я рекомендую сделать apt-get remove manpages-ru.</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2009/06/16/recursive.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Читаете ли вы perlop?</title>
		<link>http://bappoy.pp.ru/2009/06/03/reading-perldoc.html</link>
		<comments>http://bappoy.pp.ru/2009/06/03/reading-perldoc.html#comments</comments>
		<pubDate>Wed, 03 Jun 2009 14:30:13 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[perldoc]]></category>
		<category><![CDATA[переводы]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=660</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F06%2F03%2Freading-perldoc.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F06%2F03%2Freading-perldoc.html" height="61" width="51" /></a></div><p>Еще немного про perl. Перелистывая Perl Cookbook, вдруг осознал, что никогда не задумывался о возможностях оператора диапазона &laquo;<code>..</code>&laquo;. То есть, конечно, понятно, что в списковом контексте он вернет список значений от левого операнда до правого и конструкция <code>foreach(1 .. 5)</code> превратится в начало натурального ряда. А вот про то, что в скалярном контексте этот оператор ведет себя наподобие диапазона в sed, я не знал. Например, часто возникающая задача &laquo;сделать что-то с данными между открывающей и закрывающей строкой&raquo; решается просто и элегантно:</p>
<pre>perl -ne 'print if /&lt;Directory /i .. /&lt;\/Directory&gt;/i' httpd.conf</pre>
<p>Благодаря кажущейся простоте этого оператора (зачем читать доку про такие элементарные вещи, если в первом попавшемся букваре по перлу написано, что именно делает этот оператор) редкая птица удосужится ознакомиться с описанием <code>..</code> в perlop, что и приводит к подобным открытиям. </p>
<p>Не последнюю роль тут играет и местами довольно сложный язык документации. Но мир меняется к лучшему и недавно на <a href="http://translated.by">translated.by</a> в рамках проекта <a href="http://github.com/sharifulin/pod2-ru/tree">pod2-ru</a> под руководством <a href="http://sharifulin.livejournal.com/">Анатолия Шарифулина</a> народ принялся за  перевод <a href="http://translated.by/you/tags/Perl/">perldoc</a>. К настоящему моменту уже переведены: <a href="http://translated.by/you/perlbook/">perlbook</a>, <a href="http://translated.by/you/perldoc/">perldoc</a>, <a href="http://translated.by/you/perlpragma/">perlpragma</a>, <a href="http://translated.by/you/perlstyle/">perlstyle</a>; на подходе <a href="http://translated.by/you/perlintro/trans/">perlintro</a> и в процессе одна из центральных страниц документации — <a href="http://translated.by/you/perlfunc/trans/">perlfunc</a>. Также переведена примерно половина <a href="http://translated.by/you/perlboot-beginner-s-object-oriented-tutorial-1/trans/">perlboot</a>. Так что если есть желание и возможность помочь в переводе документации perl, присоединяйтесь к любому из этих переводов или начинайте свой. Даже с минимальными знаниями английского языка вы можете помочь в качестве редактора или корректора. В общем, внесите уже свой вклад в open source :)</p>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2009/06/03/reading-perldoc.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Приоритеты операторов в Perl</title>
		<link>http://bappoy.pp.ru/2009/05/15/perl-op-precedence.html</link>
		<comments>http://bappoy.pp.ru/2009/05/15/perl-op-precedence.html#comments</comments>
		<pubDate>Fri, 15 May 2009 10:46:20 +0000</pubDate>
		<dc:creator>bappoy</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[pitfalls]]></category>

		<guid isPermaLink="false">http://bappoy.pp.ru/?p=633</guid>
		<description><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F05%2F15%2Fperl-op-precedence.html"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fbappoy.pp.ru%2F2009%2F05%2F15%2Fperl-op-precedence.html" height="61" width="51" /></a></div><p>Отлаживая один скрипт, в очередной раз напоролся на банальные грабли, иллюстрирующие красоту и мощь языка Perl.</p>
<p>Сначала был примерно такой код:</p>
<div style="background:#000000;color:#ffffff; font-family:Courier,'Lucida Console','Courier New', Sans-Serif;overflow:auto;padding:0.5em;border: 1px solid #eeeeee;margin:10px;font-weight:bold;">
<font color="#ffff00"><b>while</b></font>(<font color="#00ffff"><b>&lt;STDIN&gt;</b></font>)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff00"><b>if</b></font>((<font color="#00ffff"><b>$name</b></font>) = <font color="#00ffff"><b>$_</b></font> =~ <font color="#ffff00"><b>/</b></font><font color="#ff40ff"><b>^</b></font><font color="#ff6060"><b>\s</b></font><font color="#ff6060"><b>*</b></font><font color="#ff40ff"><b>source </b></font><font color="#ff6060"><b>(.*)</b></font><font color="#ff6060"><b>\.</b></font><font color="#ff40ff"><b>sql</b></font><font color="#ffff00"><b>/i</b></font>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff00"><b>if</b></font>&nbsp;(<font color="#00ffff"><b>&amp;function</b></font>&nbsp;<font color="#00ffff"><b>$name</b></font>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#00ffff"><b># do something with $name</b></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</div>
<p>Логично было бы объединить два условия в одно:</p>
<div style="background:#000000;color:#ffffff; font-family:Courier,'Lucida Console','Courier New', Sans-Serif;overflow:auto;padding:0.5em;border: 1px solid #eeeeee;margin:10px;font-weight:bold;">
<font color="#ffff00"><b>while</b></font>(<font color="#00ffff"><b>&lt;STDIN&gt;</b></font>)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ffff00"><b>if</b></font>((<font color="#00ffff"><b>$name</b></font>) = <font color="#00ffff"><b>$_</b></font> =~ <font color="#ffff00"><b>/</b></font><font color="#ff40ff"><b>^</b></font><font color="#ff6060"><b>\s</b></font><font color="#ff6060"><b>*</b></font><font color="#ff40ff"><b>source </b></font><font color="#ff6060"><b>(.*)</b></font><font color="#ff6060"><b>\.</b></font><font color="#ff40ff"><b>sql</b></font><font color="#ffff00"><b>/i</b></font>&nbsp;&amp;&amp; <font color="#00ffff"><b>&amp;function</b></font>&nbsp;<font color="#00ffff"><b>$name</b></font>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#00ffff"><b># do something with $name</b></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</div>
<p>Но после этого условие стало выполняться для каждой строки STDIN, вне зависимости от того, совпадает она с шаблоном или нет. Попробуем разобраться.</p>
<p>Для простоты рассмотрим однострочник на Perl, локализующий эту проблему:</p>
<div style="background:#000000;color:#ffffff; font-family:Courier,'Lucida Console','Courier New', Sans-Serif;overflow:auto;padding:0.5em;border: 1px solid #eeeeee;margin:10px;font-weight:bold;"><font color="#ffff00"><b>echo</b></font><font color="#ff40ff"><b>&nbsp;o</b></font>|perl <font color="#ff6060"><b>-ne</b></font>&nbsp;<font color="#ffff00"><b>&#39;</b></font><font color="#ff40ff"><b>print &quot;aga\n&quot; if (($o) = $_ =~ /(a)/ &amp;&amp; 1)</b></font><font color="#ffff00"><b>&#39;</b></font></div>
<p>Здесь в одном условии встречаются три оператора: присваивания <code>=</code>, привязки <code>=~</code>, а также логическое И <code>&#038;&#038;</code>. Согласно <code>perldoc&nbsp;perlop</code>, оператор присваивания имеет более низкий приоритет, чем два остальных, поэтому выполняется последним, и код можно представить в виде:</p>
<div style="background:#000000;color:#ffffff; font-family:Courier,'Lucida Console','Courier New', Sans-Serif;overflow:auto;padding:0.5em;border: 1px solid #eeeeee;margin:10px;font-weight:bold;"><font color="#ffff00"><b>echo</b></font><font color="#ff40ff"><b>&nbsp;o</b></font>|perl <font color="#ff6060"><b>-ne</b></font>&nbsp;<font color="#ffff00"><b>&#39;</b></font><font color="#ff40ff"><b>print &quot;aga\n&quot; if (($o) = <span style="font-size:170%">(</span> $_ =~ /(a)/ &amp;&amp; 1 <span style="font-size:170%">)</span> )</b></font><font color="#ffff00"><b>&#39;</b></font></div>
<p>Логическая операция в больших скобках в списковом контексте возвращает  массив, содержащий пустое значение, операция присваивания выполняется успешно и условие выполняется.</p>
<p>Поэтому при объединении условий всегда нужно проверять приоритеты операторов и группировать условия вручную:</p>
<div style="background:#000000;color:#ffffff; font-family:Courier,'Lucida Console','Courier New', Sans-Serif;overflow:auto;padding:0.5em;border: 1px solid #eeeeee;margin:10px;font-weight:bold;">while<font color="#8080ff"><b>(</b></font><font color="#ff6060"><b>&lt;STDIN&gt;</b></font><font color="#8080ff"><b>)</b></font><br /><font color="#ff6060"><b>{</b></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;if<font color="#ffff00"><b>(</b></font>&nbsp;<font color="#ffff00"><b><span style="font-size:170%">(</span></b></font>&nbsp;<font color="#ffff00"><b>(</b></font><font color="#8080ff"><b>$name</b></font><font color="#ffff00"><b>)</b></font><font color="#ffff00"><b>=</b></font><font color="#8080ff"><b>$_</b></font><font color="#ffff00"><b>=</b></font>~/^<font color="#ff6060"><b>\s</b></font>*source <font color="#ffff00"><b>(</b></font>.*<font color="#ffff00"><b>)</b></font><font color="#ff6060"><b>\.</b></font>sql/i <font color="#ffff00"><b><span style="font-size:170%">)</span></b></font>&nbsp;<font color="#ffff00"><b>&amp;&amp;</b></font>&nbsp;<font color="#00ffff"><b>&amp;function</b></font> <font color="#8080ff"><b>$name</b></font><font color="#ffff00"><b>)</b></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff6060"><b>{</b></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color="#00ffff"><b># do something with $name</b></font><br />
&nbsp;&nbsp;&nbsp;&nbsp;<font color="#ff6060"><b>}</b></font><br />
<font color="#ff6060"><b>}</b></font></div>
]]></description>
		<wfw:commentRss>http://bappoy.pp.ru/2009/05/15/perl-op-precedence.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
