tag:blogger.com,1999:blog-7405301416760914652024-03-13T11:06:20.333-07:00Лучше сейчасчем никогдаivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.comBlogger57125tag:blogger.com,1999:blog-740530141676091465.post-73659447856867474752012-04-23T13:49:00.000-07:002012-04-23T13:49:45.746-07:00PowerShell - путь к успеху<div dir="ltr" style="text-align: left;" trbidi="on">
PowerShell - некое расширение cmd.exe, плотно взаимодействующее с .NET, позволяющее выполнять различные команды и тем самым автоматизировать работу в системе. Есть возможность удаленного подключения во второй версии, прямо как SSH!<br />
Правда сам язык команд крайне сложен в понимании, а справка организована весьма плачевно. Тем не менее, это уже хоть что-то.<br />
<br />
В современных виндоусах он присутствует по умолчанию, в старых версиях же придется немного попотеть, доустановив нужные компоненты:<br />
1. NET. Framework 2.0 SP1<br />
2. Windows Management Framework Core<br />
<br />
Но до нормальной работы, удаленного управления и выполнения скриптов нас ждет увлекательное путешествие, так как по понятиям Майкрософт пользователь - главный враг системы.<br />
<br />
Для того, чтобы иметь возможность подключаться к компьютеру удаленно через PowerShell, нужно для начала активировать эту возможность:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">Enable-PSRemoting</span></blockquote>
Кроме того, нужно быть в списке доверенных хостов, по умолчанию там никого нет. Не будем долго запариваться и разрешим всем хостам соединяться:<br />
<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
Set-Item WSMan:\localhost\Client\TrustedHosts *</blockquote>
Ну и последним сюрпризом стало то, что просто так скрипты не запустишь, их выполнение либо совсем отключено, либо они должны быть подписаны! Для устранения этого недостатка просто изменим политику:<br />
<blockquote class="tr_bq">
<div style="font-family: "Courier New",Courier,monospace;">
Set-ExecutionPolicy Unrestricted</div>
</blockquote>
После всех этих манипуляций наконец-то придем к успеху - удаленному запуску скриптов на машине с PowerShell:<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">Invoke-Command -ComputerName "mycomfyserver" -credential Administrator -FilePath D:\myscript.ps1</span> </blockquote>
</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com2tag:blogger.com,1999:blog-740530141676091465.post-16320879720903479612012-04-17T02:01:00.001-07:002012-04-17T09:46:16.614-07:00Шифрование AES с помощью pycrypto<div dir="ltr" style="text-align: left;" trbidi="on">
Pycrypto - весьма удобный модуль, в котором реализованы различные схемы шифрования. Вот простой пример, как можно шифровать и расшифровывать данные с помощью симметричного AES:<br />
<blockquote class="tr_bq" style="font-family: "Courier New",Courier,monospace;">
from Crypto.Cipher import AES<br />
import base64<br />
import os<br />
<br />
# размер блока шифрования<br />
BLOCK_SIZE = 32<br />
<br />
# символ, использующийся для дополнения шифруемых данных<br />
# до размера, кратного 32 байтам<br />
PADDING = '{'<br />
<br />
# функция дополнения<br />
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING<br />
<br />
# функции шифрования и расшифрования<br />
# результат дополнительно обертывается в base64<br />
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))<br />
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)<br />
<br />
# генерируем ключ<br />
secret = os.urandom(BLOCK_SIZE)<br />
<br />
# создаем объект<br />
cipher = AES.new(secret)<br />
<br />
# шифруем строку<br />
encoded = EncodeAES(cipher, 'password')<br />
print 'Encrypted string:', encoded<br />
<br />
# расшифровываем строку<br />
decoded = DecodeAES(cipher, encoded)<br />
print 'Decrypted string:', decoded</blockquote>
<span style="font-family: inherit;">Как видно, все достаточно просто, а главное полезно. Таким образом можно шифровать трафик, конфиги с критичной инфой или что-то ещё. При этом конечно необходимо как-то защитить сам ключ, например, скомпилировав скрипт в бинарник и навесив на него всяческих коварных крипторов.</span></div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com2tag:blogger.com,1999:blog-740530141676091465.post-75403918951378274612012-04-10T04:37:00.000-07:002012-04-10T04:37:10.085-07:00Python и перенос строк в файлах<div dir="ltr" style="text-align: left;" trbidi="on">
Многим известно, что в разных системах перенос строки в файлах обозначается разным образом. Например, в Windows это CR+LF (0x0d + 0x0a), а в *NIX это просто LF.<br />
Самое интересное, когда нам нужно в винде сформировать файл с переносами строк под линукс или наоборот.<br />
Представим, что мы открыли файл в режиме w, что я делаю обычно на автомате. <br />
Если мы будем писать типа file.write('qwerty\n'), то в файл запишется CR+LF. Аналогично произойдет, если заменить \n на \x0a. А если писать просто file.write('qwerty'), то никакого переноса не будет. Оказывается открывая файл в режиме w при записи строки к ней автоматически добавляется перенос строки в системном формате.<br />
<br />
В этом случае нам поможет открытие файла в бинарном режиме, то есть wb. Тогда никакого безобразия с добавлением виндовых переносов строк не происходит и мы можем со спокойной совестью писать file.write('qwerty\n').</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com2tag:blogger.com,1999:blog-740530141676091465.post-33490734515015755202012-02-20T00:16:00.000-08:002012-02-20T00:16:39.034-08:00HOWTO: Взломать Wi-Fi за 10 часов<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.xakep.ru/magazine/xa/158/158.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.xakep.ru/magazine/xa/158/158.jpg" /></a></div>
В грядущем номере журнала Хакер выходит мой материал по взлому Wi-Fi. Не пропустите!</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-54790896708372718582012-01-24T04:21:00.000-08:002012-01-24T04:21:16.781-08:00Конвертация MyISAM -> InnoDB<div dir="ltr" style="text-align: left;" trbidi="on">
По мотивам предыдущего поста. :))<br />
В интернете много всяких заметок по поводу преобразования MyISAM в InnoDB: и с помощью всяких скриптов, и утилит типа <span style="font-family: 'Courier New', Courier, monospace;">mysql_convert_table_format</span>, и даже с помощью <span style="font-family: 'Courier New', Courier, monospace;">sed</span>. Но нам сложности не нужны, поэтому предлагаю самый простой вариант. Во-первых, остановим сервер:<br />
<blockquote class="tr_bq">
<span style="font-family: 'Courier New', Courier, monospace;"># /etc/rc.d/mysql-server stop</span></blockquote>
Затем нужно убедиться, что в конфиге <span style="font-family: 'Courier New', Courier, monospace;">/etc/mysql/my.cnf</span> нет строчки <span style="font-family: 'Courier New', Courier, monospace;">skip-innodb</span>, а также присутствует строчка типа:<br />
<blockquote class="tr_bq">
<span style="font-family: 'Courier New', Courier, monospace;">innodb_data_file_path = ibdata1:100M:autoextend</span></blockquote>
<span style="font-family: inherit;">Затем логинимся в консоль MySQL:</span><br />
<blockquote class="tr_bq">
<span style="font-family: 'Courier New', Courier, monospace;">mysql -u <username> -p</span></blockquote>
И вводим команду:<br />
<blockquote class="tr_bq">
<span style="font-family: 'Courier New', Courier, monospace;">ALTER TABLE <tablename> ENGINE='InnoDB';</span></blockquote>
Вот и всё! Моя гиговая табличка преобразовалась за шесть минут.<br />
<br />
PS: конечно, рекомендую сделать бекап базы прежде чем конвертировать - на всякий случай.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com7tag:blogger.com,1999:blog-740530141676091465.post-85225318412466695272012-01-12T13:38:00.000-08:002012-01-12T13:38:50.562-08:00Восстановление MySQL MyISAM<div dir="ltr" style="text-align: left;" trbidi="on">
Если у вас в логах внезапно начали появляться ошибки типа <span style="font-family: 'Courier New', Courier, monospace;">"Table './mybd/cw_table' is marked as crashed and last (automatic?) repair failed"</span>, то значит наш дорогой MyISAM дал сбой. А так как автовосстановления в нем не предусмотрели, то придется вручную нам это сделать. Во-первых, остановим сервер mysql:<br />
<blockquote class="tr_bq">
<span style="font-family: 'Courier New', Courier, monospace;"># /etc/rc.d/mysql-server stop</span></blockquote>
Воспользуемся утилитой <b>myisamchk</b> для восстановления таблицы с ключом <span style="font-family: 'Courier New', Courier, monospace;">-r</span>, что означает recovery:<br />
<blockquote class="tr_bq">
<span style="font-family: 'Courier New', Courier, monospace;"># myisamchk -r cw_table</span></blockquote>
Это помогает в большинстве случаев. При запущенных случаях, если посыпались много таблиц, то можно проверить всю базу целиком:<br />
<blockquote class="tr_bq">
<span style="font-family: 'Courier New', Courier, monospace;"># myisamchk --silent --force --fast --update-state /var/lib/mysql/mybd/*.MYI</span></blockquote>
Если сбои произошли в результате смерти жесткого диска и файлы восстановлялись с помощью черной магии, то вместо опции <span style="font-family: 'Courier New', Courier, monospace;">--fast</span> лучше задать <span style="font-family: 'Courier New', Courier, monospace;">--medium-check</span> или же <span style="font-family: 'Courier New', Courier, monospace;">--extended-check</span>, если времени вагон / небольшие таблицы / мало индексов.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com1tag:blogger.com,1999:blog-740530141676091465.post-90433494069466072522011-12-15T11:43:00.000-08:002011-12-15T11:43:24.424-08:00Задачи на собеседованиях<div dir="ltr" style="text-align: left;" trbidi="on">
В декабрьском номере журнала <a href="http://xakep.ru/">Хакер</a> под моим чутким руководством стартовала новая ежемесячная рубрика про задачи на собеседованиях. Прошу высказывать здесь все пожелания и замечания!<br />
<br />
Предложения по задачам для последующих выпусков складывайте сюда же.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com3tag:blogger.com,1999:blog-740530141676091465.post-75496546643105894192011-11-08T13:00:00.000-08:002011-11-08T13:00:36.633-08:00Экспресс курс по сортировкам или вспомнить всё<div dir="ltr" style="text-align: left;" trbidi="on">
1. <b>Пузырьком</b> О(n^2). Два вложенных цикла, во внутреннем сравниваются пары соседних элементов, начиная с нижних. Таким образом за один проход внутреннего цикла получаем один отсортированный элемент на своем месте.<br />
<br />
2. <b>Выбором</b> О(n^2). В исходном массиве ищем наименьший элемент и меняем его с первым. Далее повторяем эти шаги с подмассивом исходного, куда не входит уже отсортированный первый элемент.<br />
<br />
3. <b>Вставками</b> O(n^2). Все элементы условно разделяются на готовую последовательность a1 ... ai-1 и входную ai ... an. Hа каждом шаге, начиная с i = 2 и увеличивая i на 1, берем i-й элемент входной последовательности и вставляем его на нужное место в готовую.<br />
<br />
4. <b>Шелла</b> O(n log^2 n). Некая модификация сортировки вставками: здесь сначала сортируется не весь массив, а группы элементов, отстоящих друг от груга на некоторое расстояние d. Это расстояние постепенно уменьшаем и доходим до того, что сортируем опять же весь массив. Например, для массива 16 элементов разумно выбрать начальное d = 8, а потом уменьшать его в два раза. Сначала будет сортироваться 8 групп по 2 элемента, потом 4 группы по 4 и так далее.<br />
<br />
5. <b>Пирамидальная</b> O(n log n). Из исходного массива сначала строится пирамида. Она является так же сбалансированным деревом и обладает свойством, что каждый элемент меньше либо равен родителю. Это дерево легко вписывается в массив, если вписывать элементы по порядку - слева направо и сверху вниз. Далее первый элемент (максимальный) меняем с последним (минимальным) и забываем его, т.е. не учитываем в пирамиде. Перестраиваем пирамиду согласно свойству, т.е. просеиваем первый элемент вниз. Повторяем шаги пока пирамида не иссякнет.<br />
<br />
6. <b>Быстрая</b> O(n log n). Из массива выбирается некоторый опорный элемент a[i]. Запускается процедура разделения массива, которая перемещает все ключи, меньшие, либо равные a[i], влево от него, а все ключи, большие, либо равные a[i] - вправо.<br />
Теперь массив состоит из двух подмножеств, причем левое меньше, либо равно правого. Для обоих подмассивов: если в подмассиве более двух элементов, рекурсивно запускаем для него ту же процедуру.<br />
<br />
7. <b>Поразрядная</b> O(nk). Итак, в этом алгоритме у нас есть некие вспомогательные списки, называемые карманами. Их количество равно разрядности данных, например, для человеческих чисел = 10. Вначале они пустые и в них добавляются элементы нашего массива согласно значению первого разряда. Далее полученные списки склеиваются, и операция повторяется над полученным массивом, но только со 2 разрядом. И далее вплоть до максимального разряда самого длинного числа.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-49130424803936490502011-10-20T14:10:00.000-07:002011-10-20T14:10:56.081-07:00Matplotlib - анимация в реальных условиях<div dir="ltr" style="text-align: left;" trbidi="on">
На сайте проекта - <a href="http://matplotlib.sourceforge.net/examples/index.html">http://matplotlib.sourceforge.net/examples/index.html</a> - даны базовые примеры анимации с графиками, которые, как обычно бывает, плохо работают в боевых условиях. Например, у меня имеется прога на GTK, с отдельным потоком, где производятся все вычисления для графиков. По-хорошему, там же и надо вызывать функцию перерисовки, но не тут-то было!<br />
<br />
Иксы выкатывают мне неведомую ошибку:<br />
<blockquote>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">The program 'panel.py' received an X Window System error.
This probably reflects a bug in the program.
The error was 'BadDrawable (invalid Pixmap or Window parameter)'.
(Details: serial 6974 error_code 9 request_code 62 minor_code 0)
(Note to programmers: normally, X errors are reported asynchronously;
that is, you will receive the error a while after causing it.
To debug your program, run it with the --sync command line
option to change this behavior. You can then get a meaningful
backtrace from your debugger if you break on the gdk_x_error() function.)
</span></blockquote>
Я так и не понял почему такое может происходить, поэтому начал искать другой способ запуска функции через определенный промежуток времени. В этом мне помог такой кодес:<br />
<blockquote>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">import gobject
</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">gobject.timeout_add(1000, self.animate)</span></blockquote>
Такой замес тупо вызывает функцию animate каждую секунду. Все довольны!</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-71580633755611694032011-10-07T08:29:00.000-07:002011-10-07T08:29:24.493-07:00Подключение некоторых Android 2.3 based устройств к Linux<div dir="ltr" style="text-align: left;" trbidi="on">
Не знаю уж почему так делают, но на некоторых прошивках Android 2.3 при подключении к компу устройство по умолчанию распознается как модем, а не как флешка, что сопровождается подобными деферамбами dmesg:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;">
[81405.955234] usb 2-2: new high speed USB device number 7 using ehci_hcd<br />[81406.098927] cdc_acm 2-2:1.0: This device cannot do calls on its own. It is not a modem.<br />[81406.099041] cdc_acm 2-2:1.0: ttyACM0: USB ACM device</blockquote>
На этом всё, то есть как флешка оно не определяется. Итак, чтобы исправить это, заходим в телефон и набираем номер <b>*#7284#</b>, выскочит некая PhoneUtil, где и надо выбрать в обоих случаях пункт PDA. Вот и всё, теперь андроид монтируется как в старые добрые времена.</div>
ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-36100085342460290292011-08-28T10:57:00.000-07:002011-08-28T10:57:53.110-07:00Перепрошивка Galaxy Tab на Android 2.3<div dir="ltr" style="text-align: left;" trbidi="on">Samsung уже давно анонсировал обновление Android 2.3 для Galaxy Tab, но официально распространять его в нашей стране не торопится. Мне это надоело и я решил перепрошить свой девайс самостоятельно итальянской версией системы.<br />
Для этого воспользуемся прогой <a href="https://github.com/downloads/Benjamin-Dobell/Heimdall/heimdall_1.3.0_i386.deb">heimdall</a>, которая является кроссплатформенной, в отличие от остальных:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;"># dpkg -i heimdall_1.3.0_i386.deb</blockquote>Далее нужно скачать саму прошивку, можно <a href="http://narod.ru/disk/18621291001/P1000BGJP4_CSC-RUS_GTU_WOPA_WITHBOOT_PREROOTED_ZEROLAB-DOT-NET.zip">отсюда</a>. После этого распаковываем tar в отдельную папку и добавляем туда файл P1_add_hidden.pit из основного архива. Потом переводим наш планшет в режим перепрошивки, для этого надо выключить его, а потом зажать кнопку включения и кнопку понижения громкости пока не появится значок с гастарбайтером. Подключаем девайс к компу через usb и вводим команду:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;">$ heimdall flash --repartition --pit P1_add_hidden.pit --cache cache.rfs --dbdata dbdata.rfs --factoryfs factoryfs.rfs --kernel zImage</blockquote>Всё! Перепрошивка занимает несколько минут, потом устройство само перезагрузится и можно начинать переустанавливать весь софт. =\</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-23548546117628402102011-08-19T16:34:00.000-07:002011-08-19T16:50:42.036-07:00MySQL и Python<div dir="ltr" style="text-align: left;" trbidi="on">Итак, тут я расскажу как быстро развернуть СУБД мускуль и рулить ей из питона. Начнем. Сперва установим нужные пакеты. Мускуль:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;"># apt-get install mysql-server</blockquote>В процессе установки спросят пароль для рута, лучше ввести что-нибудь и не забыть! Ставим модуль для питона:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;"># apt-get install python-mysqldb</blockquote>Ну вот, после этого было бы неплохо создать базу данных и пользователя к ней. Логинимся под рутом:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;">$ mysql -u root -p</blockquote>Создаем базу:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;">mysql> CREATE DATABASE testdb;</blockquote>Создаем пользователя с паролем 'test', даем все права и выходим:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;">mysql> CREATE USER 'user'@'localhost' IDENTIFIED BY 'test';<br />
mysql> USE testdb;<br />
mysql> GRANT ALL ON testdb.* TO 'user'@'localhost';<br />
mysql> quit;</blockquote>Теперь небольшой пример:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;">import MySQLdb as mdb<br />
<br />
conn = mdb.connect('localhost', 'user', 'test', 'testdb')<br />
cursor = conn.cursor()<br />
cursor.execute("SELECT VERSION()")<br />
data = cursor.fetchone()<br />
print data<br />
cursor.close()<br />
conn.close()</blockquote>Здесь просто выполняется запрос "SELECT VERSION()" и соотвественно версия субд выводится на экран. Функция fetchone() возвращает одну строку. Если запрос возвращает множество строк, то чтобы их получить можно использовать fetchall(). Но если записей очень много, то это может быть расточительно для памяти. В таком случае нам поможет атрибут rowcount, где содержится количество строк, которое вернул запрос:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;">cursor.execute("SELECT * FROM table")<br />
numrows = int(cursor.rowcount)<br />
for i in xrange(numrows):<br />
row = cursor.fetchone()<br />
print row</blockquote>Кстати, row представляет из себя кортеж, так что можно с легкостью получить доступ к каждому элементу выборки. Ну а дальнейшие изыскания ограничиваются только вашими знаниями языка SQL!</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-42897240784790174942011-08-19T15:47:00.000-07:002011-08-19T15:47:09.184-07:00Python + Excel или создаем отчеты в формате XLS<div dir="ltr" style="text-align: left;" trbidi="on">Создавать экселевские файлы в питоне элементарно! Для этого есть модуль <a href="http://pypi.python.org/pypi/xlwt">xlwt</a>. Ставим:<br />
<blockquote><div style="font-family: "Courier New",Courier,monospace;"># apt-get install python-xlwt</div></blockquote>Простейший пример:<br />
<blockquote style="font-family: "Courier New",Courier,monospace;">import xlwt<br />
<br />
# тут важно поставить 'utf-8', если надо писать русские символы и так далее<br />
wbk = xlwt.Workbook('utf-8')<br />
# добавляем лист<br />
sheet = wbk.add_sheet('sheet 1')<br />
# пишем в первую строку и первый столбец<br />
sheet.write(0, 0, 'bla bla')<br />
# сохраняем в файл <br />
wbk.save('test.xls')</blockquote>Вот и всё! Конечно, функционал модуля этим не ограничивается, все интересующиеся могут ознакомиться с ним на страницах документации.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-11771339870502435942011-07-24T05:38:00.000-07:002011-07-24T05:38:32.969-07:00Установка Linux на долбаную флешку<div dir="ltr" style="text-align: left;" trbidi="on">Сегодня я закоспектирую тут, как правильно ставить НЕ live дистрибутив Linux на флешку, в моем случае Debian, а то я забываю некоторые моменты и парюсь с этим каждый раз. =\<br />
<br />
Итак, всё начинается с форматирования флешки с помощью <b>fdisk</b> и <b>mkfs</b>. Я ставлю ФС ext2, потому что там нет журналирования, а с журналом флешка быстро загнется. Можно воспользоваться и ext3/4 с отключенным журналом, но это дополнительный гемор. Кстати, рекомедую раздел создавать именованый, потом станет понятно зачем:<br />
<b># mkfs.ext2 -L TRANSCEND /dev/sdc1</b><br />
<br />
Монтируем флешку:<br />
<b># mount /dev/sdc1 /mnt</b><br />
<br />
Ставим туда базовую систему:<br />
<b># debootstrap --arch i386 lenny /mnt</b><br />
<br />
Для Debian есть специальная утилита <b>debootstrap</b>, для других дистров может и нет, но можно и вручную залить туда из образа, например. После установки чрутимся в нашу новую системку:<br />
<b># chroot /mnt /bin/bash</b><br />
<br />
В этой системе уже можем делать что-нибудь, ставить пакеты например, но для начала надо апдейтнуть список, чтобы APT не ругался на не подписанные пакеты. Ну и сразу поставим GRUB и ядро:<br />
<b># apt-get update</b><br />
<b># apt-get install linux-image-2.6-686 grub</b><br />
<br />
Пишем в <b>/etc/fstab</b> такую инфу, чтобы все правильно монтировалось:<br />
<blockquote><i>LABEL=TRANSCEND / ext2 defaults,errors=remount-ro,noatime 0 1</i><br />
<i>proc /proc proc defaults 0 0</i><br />
<i>tmpfs /tmp tmpfs defaults,noatime 0 0</i><br />
<i>tmpfs /var/lock tmpfs defaults,noatime 0 0</i><br />
<i>tmpfs /var/log tmpfs defaults,noatime 0 0</i><br />
<i>tmpfs /var/run tmpfs defaults,noatime 0 0</i><br />
<i>tmpfs /var/tmp tmpfs defaults,noatime 0 0</i></blockquote>И после этого начинается самая шляпа - надо сделать флешку загрузочной. Из основной системы ставим GRUB в MBR флешки:<br />
<b># grub-install --root-directory=/mnt /dev/sdc</b><br />
<br />
И можно уже попробовать загрузиться, НО! Проблема в том ,что Lenny использует GRUB 0.**, а все более-менее современные системы - GRUB 1.**, а они смотрят конфиги в разных местах, <b>/boot/grub/menu.lst</b> и <b>/boot/grub/grub.cfg</b> соотвественно. Грузимся через QEMU:<br />
<b># qemu -hda /dev/sdc</b><br />
<br />
Получаем консоль граба, который не нашел конфиг, вводим туда такие фразы:<br />
<b>set root=(hd0,msdos1)</b><br />
<b>linux /vmlinuz root=LABEL=TRANSCEND</b><br />
<b>initrd /initrd.img</b><br />
<b>boot</b><br />
<br />
Все! Система загружается. Дальше логинимся под рутом без пароля и ставим нужный GRUB в MBR:<br />
<b># update-grub</b><br />
<b># grub-install /dev/hda</b><br />
<br />
Последний момент, надо в /boot/grub/menu.lst задать корень через метку флешки, потому что на разных компах файлы устройства флешки могут различаться:<br />
<br />
<b>kernel /boot/vmlinuz-2.6.22-3-686 root=LABEL=TRANSCEND ro</b></div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com3tag:blogger.com,1999:blog-740530141676091465.post-72989439496159784842011-06-26T16:02:00.000-07:002011-06-26T16:02:23.491-07:00Работа с COM портом в python: PyVISA или pySerial?<div dir="ltr" style="text-align: left;" trbidi="on">Для питона существует два модуля для работы с последовательными портами, я бы однозначно рекомендовал pySerial по нескольким причинам:<br />
<br />
1. PyVISA сложен в установке, нужно дополнительно устанавливать библиотеку nivisa.<br />
2. PyVISA не видит эмулированный через USB последовательный порт (т.е. переходник USB->COM).<br />
3. В PyVISA нельзя задавать порт напрямую через файл устройства, например, в случае переходника USB->COM это будет /dev/ttyUSB0.<br />
<br />
PySerial всех этих недостатков лишен, при этом очень прост в использовании. При работе с последовательным портом не надо забывать выставить одинаковые настойки на компе и собственно устройстве, в особенности это касается скорости передачи и бита четности. Все настройки могут задаваться при создании экземпляра объекта Serial или после через атрибуты.<br />
<br />
<a href="http://pyserial.sourceforge.net/pyserial_api.html">Страница документации</a>.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com1tag:blogger.com,1999:blog-740530141676091465.post-72960604217545969362011-05-29T18:20:00.000-07:002011-05-29T18:20:14.528-07:00Парсим логи при помощи генераторов - 2<div dir="ltr" style="text-align: left;" trbidi="on">Дано: сотни логов веб-сервера, разбросанные по разным директориям. Возможно, заархивированные.<br />
Требуется: понять сколько байтов было передано :)<br />
<br />
В питоне есть замечательная функция os.walk(), позволяющая блуждать по файловой системе:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">import os</div><div style="font-family: "Courier New",Courier,monospace;"><br />
</div><div style="font-family: "Courier New",Courier,monospace;">for path, dirlist, filelist in os.walk(topdir):</div><div style="font-family: "Courier New",Courier,monospace;"> # path : текущая директория</div><div style="font-family: "Courier New",Courier,monospace;"> # dirlist : список поддиректорий</div><div style="font-family: "Courier New",Courier,monospace;"> # filelist : список файлов</div><div style="font-family: "Courier New",Courier,monospace;"> ...</div><br />
Для достижения цели потребуется создать несколько функций:<br />
1. Функция-генератор, возвращающая список файлов по заданному шаблону:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">import os<br />
import fnmatch<br />
</div><div style="font-family: "Courier New",Courier,monospace;">def gen_find(filepat,top):<br />
for path, dirlist, filelist in os.walk(top):<br />
for name in fnmatch.filter(filelist, filepat):<br />
yield os.path.join(path, name)</div><br />
Примеры использования:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">pyfiles = gen_find('*.py', '/')<br />
logs = gen_find('access-log*', '/usr/www/')</div><br />
2. Функция-генератор, которая принимает список файлов, и, если среди них есть архивы, то возвращает распакованные файлы. Если файл не архив, то просто открывает его:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">import gzip</div><div style="font-family: "Courier New",Courier,monospace;">import bz2<br />
</div><div style="font-family: "Courier New",Courier,monospace;">def gen_open(filenames):<br />
for name in filenames:<br />
if name.endswith(".gz"):<br />
yield gzip.open(name)<br />
elif name.endswith(".bz2"):<br />
yield bz2.BZ2File(name)<br />
else:<br />
yield open(name)</div><br />
3. Функция (разумеется генератор), которая возвращает единую последовательность результатов, принимая при этом несколько последовательностей (в нашем случае передаем открытые файлы, а получаем последовательность строк):<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">def gen_cat(sources):</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> for s in sources:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> for item in s:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> yield item</span><br />
<br />
Ну вот, после реализации всех этих функций осталось только немного подправить прошлый исходник, чтобы он теперь работал с любым количеством файлов:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">filenames = gen_find('access-log*', '/usr/www')<br />
logfiles = gen_open(filenames)<br />
loglines = gen_cat(logfiles)<br />
bytecolumn = (line.rsplit(None, 1)[1] for line in loglines)<br />
bytes = (int(x) for x in bytecolumn if x != '-')<br />
print "Total", sum(bytes)</div><br />
Особые эстеты могут свернуть этот исходник вплоть до 1 строчки, благодаря тому факту, что в питоне все функции - высшего порядка.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-70780469003400715212011-05-29T16:10:00.000-07:002011-05-29T16:10:58.015-07:00Парсим логи при помощи генераторов<div dir="ltr" style="text-align: left;" trbidi="on">Задача: понять по логам Apache сколько байтов мы передали.<br />
NB: файлы мб большие (несколько гигов).<br />
<br />
Формат логов примерно следуюший:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">217.168.25.4 - - [28/May/2011:14:06:27 +0400] "GET / HTTP/1.0 200 8509</div><br />
Надо получать из каждой строки последнюю циферку, при этом если ничего не передавалось в запросе (например, произошла ошибка), то вместо циферки будет дефис. Как и в прошлый раз предлагаю два варианта: быдлокодерский и православный. Итак, номер один, без использования генератора:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">wwwlog = open("access-log")</div><div style="font-family: "Courier New",Courier,monospace;">total = 0</div><div style="font-family: "Courier New",Courier,monospace;">for line in wwwlog:</div><div style="font-family: "Courier New",Courier,monospace;"> bytestr = line.rsplit(None,1)[1]</div><div style="font-family: "Courier New",Courier,monospace;"> if bytestr != '-':</div><div style="font-family: "Courier New",Courier,monospace;"> total += int(bytestr)</div><div style="font-family: "Courier New",Courier,monospace;">print "Total", total</div><br />
И, с генератором:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">wwwlog = open("access-log")</div><div style="font-family: "Courier New",Courier,monospace;">bytecolumn = (line.rsplit(None,1)[1] for line in wwwlog)</div><div style="font-family: "Courier New",Courier,monospace;">bytes = (int(x) for x in bytecolumn if x != '-')</div><div style="font-family: "Courier New",Courier,monospace;">print "Total", sum(bytes)</div><div style="font-family: "Trebuchet MS",sans-serif;"><br />
</div><div style="font-family: "Trebuchet MS",sans-serif;"><span style="font-family: inherit;">Выглядит компактнее, не правда ли? В данном случае используется выражение-генератор, эдакий "цикл for наоборот", который выдает кортеж из результатов</span>, суммирующийся далее.</div></div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-55923332219460492612011-05-18T07:22:00.000-07:002011-05-18T07:22:57.311-07:00Скрипт для скачивания содержимого по ссылкам<div dir="ltr" style="text-align: left;" trbidi="on">Тестовое задание в одной конторе (не будем называть пальцем):<br />
<br />
<i>Напишите скрипт, который будет считывать список URL из файла (одна строка - один URL), скачивать их не более чем в N потоков и сохранять каждую страницу в отдельный файл. N задается аргументом командной строки и по умолчанию равно 10. Имена результирующих файлов значения</i><br />
<i>не имеют.</i><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"></span><span style="font-family: inherit;">import sys</span><br style="font-family: inherit;" /><span style="font-family: inherit;">import threading</span><br style="font-family: inherit;" /><span style="font-family: inherit;">import Queue</span><br style="font-family: inherit;" /><span style="font-family: inherit;">import urllib2</span><br style="font-family: inherit;" /><br style="font-family: inherit;" /><span style="font-family: inherit;">class DownloadThread(threading.Thread):</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> def run(self):</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> headers = {'User-Agent' : 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)'}</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> while urlsPool.qsize() > 0:</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> logfile = open(str(urlsPool.qsize()), 'w')</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> req = urllib2.Request(urlsPool.get(), None, headers)</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> logfile.write(urllib2.urlopen(req).read())</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> logfile.close()</span><br style="font-family: inherit;" /><br style="font-family: inherit;" /><span style="font-family: inherit;">if len(sys.argv) < 2:</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> print 'Usage: downloader.py [-n <number>] FILE\n\</span><br style="font-family: inherit;" /><span style="font-family: inherit;">"-n <number>" - number of threads (default 10)'</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> sys.exit(1)</span><br style="font-family: inherit;" /><span style="font-family: inherit;">if len(sys.argv) == 4 and sys.argv[1] == '-n':</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> threads = int(sys.argv[2])</span><br style="font-family: inherit;" /><span style="font-family: inherit;">else:</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> threads = 10</span><br style="font-family: inherit;" /><span style="font-family: inherit;">urlsPool = Queue.Queue(0)</span><br style="font-family: inherit;" /><span style="font-family: inherit;">for url in open(sys.argv[-1]):</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> urlsPool.put(url)</span><br style="font-family: inherit;" /><span style="font-family: inherit;">for x in xrange(threads):</span><br style="font-family: inherit;" /><span style="font-family: inherit;"> DownloadThread().start()</span></div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-46537157009359822042011-05-18T07:07:00.000-07:002011-05-18T07:07:40.719-07:00Немного про итераторы в питоне<div dir="ltr" style="text-align: left;" trbidi="on">В рамках акции по избавлению своих программ на питоне от быдлокода, я, как бывший программист на Си, открыл для себя много занимательных вещей. Сегодня немного про итераторы - объекты, которые позволяют программисту перебирать значения. Технически это реализуется с помощью метода next, который при каждом вызове возвращает следующий элемент коллекции. Например, так прочитает содержимое файла бывший быдлопрогаммист на Си:<br />
<br />
file = open('file.txt')<br />
while True:<br />
line = file.readline()<br />
if not line: break<br />
print line<br />
<br />
А так это сделает грамотный питонер (объект файла поддерживает итерационный протокол, который используется в цикле for):<br />
<br />
for line in open('file.txt')<br />
print line<br />
<br />
Здесь циклом for неявно вызывается метод next и в конце обрабатывается исключение StopIteration, открытие файла также происходит неявно, поэтому можно избежать проблем с памятью при работе с большими файлами.<br />
<br />
У словарей тоже есть итератор! Так можно выполнить обход всех ключей словаря:<br />
<br />
D = {'a' : 1, 'b' : 2, 'c' : 3}<br />
for key in D:<br />
print key, D[key]<br />
<br />
Итераторы в строках тоже могут быть весьма полезны. Следующий код получает и выводит на экран каждый 2 символ строки S (ещё здесь используется срез с третьим параметром, про который многие забывают):<br />
<br />
for x in S[::2]:<br />
print x<br />
<br />
Соотвествующий быдлокод, который к тому же работает медленнее, т.к. при каждом проходе цикла осуществляется доступ к объекту строки:<br />
<br />
for i in range(0, len(S), 2):<br />
print S[i]<br />
<br />
В целом в питоне любая коллекция поддерживает итерационный протокол, и его использование в коде не только способствует его компактности, но и благотворно отражается на скорости программы.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-60394728070689456872011-03-24T15:43:00.000-07:002011-03-24T15:44:20.493-07:00Бразильский танец с бубном<div dir="ltr" style="text-align: left;" trbidi="on">Очередная моя статья в свежей прессе!<br />
<br />
На этот раз рассуждал о настройке, оптимизации работы и обеспечении безопасности Samba-клиента в Linux.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><img border="0" src="http://www.xakep.ru/magazine/xa/147/147.jpg" /></div></div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-4698769926876563032011-03-22T11:48:00.000-07:002011-03-22T11:48:52.002-07:00Убираем анимацию табов в Firefox 4<div dir="ltr" style="text-align: left;" trbidi="on">Сегодня (почтенная публика уже, наверное, в курсе) состоялся релиз Firefox 4! Всё вроде хорошо: и быстрота, и простота, и так далее. Но, следуя трендам, разработчики прикрутили анимацию при открытии таба, которая лично меня ужасно раздражает.<br />
А убрать её через штатное меню настройки нельзя, а можно вот так: надо набрать в строке адреса "about:config", в фильтре ввести "tab", найти параметр browser.tabs.animate и установить его значение в false.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-80613735458906249042011-03-21T14:25:00.000-07:002011-03-21T14:27:25.294-07:00Выставляем правильное разрешение на внешнем дисплее<div dir="ltr" style="text-align: left;" trbidi="on">Как выяснилось, мой уютный ThinkPad с Арчем на борту не сильно дружит с телеком Samsung по VGA кабелю, а именно дает выставлять разрешение максимум 1024x768, хотя поддерживается там 720p (1360x768). Причину такого поведения доподлинно выяснить не удалось, но тут скорее всего два варианта: либо дрова неправильно обрабатывают <a href="http://ru.wikipedia.org/wiki/Extended_display_identification_data">EDID</a> блок, либо этот блок неправильно формируется на телеке (либо я вообще неправильно настроил иксы).<br />
Для исправления ситуации командуем, чтобы узнать параметры этого разрешения, так называемый VESA CVT mode line:<br />
<blockquote><b>$ cvt 1360 768</b></blockquote>Далее добавляем этот режим в список доступных:<br />
<blockquote><b>$ xrandr --newmode "1360x768_60.00" 84.75 1360 1432 1568 1776 768 771 781 798 -hsync +vsync</b></blockquote>И добавляем режим для конкретного выхода:<br />
<blockquote><b>$ xrandr --addmode VGA1 1360x768_60.00</b></blockquote>После этого нужное разрешение будет доступно для выбора в xrandr или фронтэнде к нему для вашего WM/DE. Я, вследствие природной лени, пользуюсь lxrandr. Чтобы каждый раз не вбивать команды, можно записать их в файлы ~/.xinitrc или ~/.xprofile - они выполнятся при старте иксов. <br />
<br />
Либо можно добавить в xorg.conf блок типа такого:<br />
<blockquote>Section "Monitor"<br />
Identifier "External VGA"<br />
Modeline "1360x768_60.00" 84.75 1360 1432 1568 1776 768 771 781 798 -hsync +vsync<br />
Option "PreferredMode" "1360x768_60.00"<br />
EndSection</blockquote></div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-77172526340178959172011-03-11T12:12:00.000-08:002011-03-11T12:12:12.631-08:00Считаем количество ненулевых битов<div dir="ltr" style="text-align: left;" trbidi="on">"Предложите способ посчитать количество ненулевых битов в содержимом файла с именем blob.dat". Предлагаю:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">#!/usr/bin/python2.7</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">def bstr(n):</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> return ''.join([str(n >> x & 1) for x in (7,6,5,4,3,2,1,0)])</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">f = file('blob.dat', 'rb')</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">bytes = f.read()</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">sheet = ''.join([bstr(ord(c)) for c in bytes])</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">amount = 0</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">for bit in sheet:</span><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;"> if bit == '1': amount += 1</span><br style="font-family: "Courier New",Courier,monospace;" /><br style="font-family: "Courier New",Courier,monospace;" /><span style="font-family: "Courier New",Courier,monospace;">print amount</span></div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com3tag:blogger.com,1999:blog-740530141676091465.post-6948764005159548932011-03-03T11:38:00.000-08:002011-03-03T12:11:37.610-08:00Скринкастинг в Linux<div dir="ltr" style="text-align: left;" trbidi="on">Вы всё ещё снимаете видео о том, как похекали сайт NASA, с помощью recordmydesktop? Не позорьтесь! Вот вам кошерная команда:<br />
<br />
<b>$ ffmpeg -f x11grab -s 1280x800 -r 25 -g 250 -i :0.0 -sameq -vcodec qtrle out.mov</b><br />
<br />
1280x800 нужно заменить в соотвествии с разрешением экрана. На мой взгляд такой набор параметров обеспечивает оптимальное соотношение скорость/качество.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0tag:blogger.com,1999:blog-740530141676091465.post-80539715015164744352011-02-26T08:12:00.000-08:002011-08-21T02:17:07.255-07:00Liberte Linux<div dir="ltr" style="text-align: left;" trbidi="on"><div dir="ltr" style="text-align: left;" trbidi="on">Чуть было не забыл, что недавно вышла в свет моя первая статья в светском журнале Хакер про дистрибутив для настоящего анонимуса! <br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://www.xakep.ru/magazine/xa/146/146.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.xakep.ru/magazine/xa/146/146.jpg" /></a></div></div><b>UPD:</b> текст статьи доступен <a href="http://www.xakep.ru/post/55953/">здесь</a>.</div>ivhttp://www.blogger.com/profile/06526424784813687531noreply@blogger.com0