2009-12-11

Pylons, SQLAlchemy, кодировка

Долгие мучения с вышеуказанной связкой побудили меня написать эту заметку.

Работа с SQLite не вызывала проблем, т.к. эта СУБД хранит данные в Unicode, и Pylons+mako по умолчанию с ним отлично работают. Просмотр данных в SQLite можно делать с помощью:
1) консольной утилиты (sudo apt-get install sqlite3)
2) SQLite Database browser (sudo apt-get install sqlitebrowser)
3) плагином для Firefox (http://code.google.com/p/sqlite-manager/)
Все они нормально отображают данные, без крякозябрей. На web-страницы шаблонизатор mako также выводит все корректно.

А вот с MySQL дело несколько сложнее, т.к. он может отдавать данные в разных кодировках. Чтобы получить данные в нужной, а не в той, что стоит в настройках сервера по умолчанию (они располагаются в /etc/mysql/my.cnf), нужно дать команду "SET NAMES кодировка".
Моя история была такова, что потребовалось данные из одной БД, которую использовала CMS Joomla, перетащить в другую, чтобы работать с ней из Pylons. Как я понял, Joomla при работе с БД использовала "SET NAMES latin1", что для англоязычных товарищей - нормально и привычно уже много лет. И все бы ничего, да есть засада.
Программы для работы с MySQL, которые я использую в основном, это:
1) MySQL Query Browser (sudo apt-get install mysql-query-browser)
2) phpMyAdmin на сервере
Эти приложения по умолчанию предпочитают кодировку соединения UTF8. Поэтому, что в одном, что в другом кириллица была видна как "ПеÑ". Есть приложения, которые справляются с этой проблемой, но в phpMyAdmin на сервере этого не исправишь.
Так что-же делать? Перевести данные из одной кодировки в другую. Мне пришлось написать скрипт, который создает два соединения с MySQL, причем в первом устанавливаю "SET NAMES latin1" (для донорской базы), во втором "SET NAMES utf8" (для новой). Остается пройтись по записям, считывая их в latin1 и записывая в utf8.
После такой обработки вышеприведенные программы отображают кириллицу как полагается. Остается только настроить Pylons и SQLAlchemy.
Итак, для корректного отображения данных нужно дать серверу MySQL команду "SET NAMES utf8". Где же это сделать? Я нашел три варианта. Предположим, проект называется app.
1) Файл /app/config/environment.py, метод load_environment
from sqlalchemy import engine_from_config
from app.model import init_model
def load_environment(global_conf, app_conf):
    engine = engine_from_config(config, 'sqlalchemy.')
    engine.execute("SET NAMES utf8")
    init_model(engine)
2) Файл /app/model/__init__.py, метод init_model
def init_model(engine):
    engine.execute("SET NAMES utf8")
В обоих случаях, при старте проекта в консоли будет видно, что эти команды выполняются. И все вроде бы пошло гладко! Но это до поры. А именно, до поры создания нового соединения.
Как известно, SQLAlchemy использует так называемый pool, т.е. некий список соединений, который использует по мере занятости, циклически. Их колличество можно менять. Пока я этого не понял, неоднократно был удивляем странным поведением пилонов. Так вот, пока хватает одного соединения, все идет как задумано, но стоит перейти на второе - косяки, вперед! "SET NAMES" для них никто не задавал, поэтому кодировка будет "как получится", а именно знаками вопросов для кириллицы. Вот тут то и пригодится третий способ. Он задает команду при создании соединения, и все pool-ы будут передавать данные с нужной кодировкой. Почитать об этом больше можно тут.
3) Файл /development.ini
sqlalchemy.url = mysql://root:@localhost:3306/church?init_command=set%20names%20%22utf8%22
sqlalchemy.convert_unicode=true
sqlalchemy.encoding='utf8'

Теперь немного о причине таких махинаций. Только таким образом мне удалось добиться того, чтобы поиск русских слов в базе данных происходил без учета регистра. В SQLite он не работает, т.к. там Unicode, и выбирать не приходится. И только в MySQL, и с данными в utf8 это получилось. Кстати, со словами, состоящими из латинских символов, проблем нет. Если есть другие способы, буду рад добавить их.

2009-12-08

Pylons и mako: Почему метод контроллера у меня вызывается дважды?

Записка на память. Ситуация:
Метод контроллера при варианте

return "ABC"

отрабатывает один раз.
При варианте

return render("/abc.mako")

метод вызывается дважды. Но не во всех шаблонах.
Причина: наличие в шаблоне строки

<link rel="stylesheet" type="text/css" href="/" media="all">

Pylons пытается подгрузить по ссылке содержимое. Если ничего не указано, то он обращается к тому же контроллеру и тому же методу, откуда вызван рендер шаблона. Стилей он там не находит, но метод срабатывает. В результате лишняя нагрузка, и ненужная деятельность.

2009-12-07

Программа для изучения Библии в Linux. Опрос.

Изначально программа для изучения Библии в ОС Linux задумывалась исключительно для этих целей. Никаких там посторонних, хоть и христианских, книжек, никаких песен или комментариев. И, пока что, так оно и остается.
Но, наконец-то братья откликнулись, и в комментариях было высказано предложение добавить возможность работы с модулями "Цитаты" Тимофея Ха либо напрямую, либо конвертировать их в формат моей разработки. Я размышляю над этим, и при возможности, займусь.
А пока что, мне было бы интересно, какие переводы Священного Писания вы считаете востребованными? Для меня RST и KJV более чем достаточно. Хотелось бы еще Женевскую учебную Библию добавить, но ее я в модулях Цитаты не нашел, а то обязательно бы прикрутил.
Прошу отписываться по этому поводу.

P.S. - самая актуальная версия - по ссылке справа вверху.

2009-11-22

Ноутбук ASUS FSKseries, Ubuntu 9.10 и наушники

Вопрос: на ноутбуке ASUS F3Kseries при установленной Ubuntu 9.10, при вставленных наушниках, звук идет и во встроенные колонки и в наушники. Хотелось бы, чтобы звучали только наушники, раз уж они воткнуты.
Ответ: открываем файл
/etc/modprobe.d/alsa-base.conf
и добавляем туда строку
options snd-hda-intel model=auto
Перезагружаем. Все работает как надо.

2009-10-19

FCKeditor + Pylons

Не так давно передо мной встала задача: подобрать и реализовать на сайте хороший WYSIWYG редактор для проекта на Pylons. Перебрав несколько вариантов, я остановился на FCKeditor, так как у него имеется встроенный менеджер медиа-файлов, т.е. присутствует механизм загрузки файлов на сервер и выборки оттуда для вставки в текст.

Все это распрекрасно, с одним маленьким НО - он не готов для прикручивания к пилонам. Нет, конечно разработчики учли присутствие на белом свете языка Python (в наличии также коннекторы для asp, aspx, cfm, lasso, perl, php). Но только как wsgi. Через mod_python, cgi - пожалуйста, все почти готово. А для меня - не очень. Поискав в интернете ответ, так и не нашел толкового пошагового решения. Потому, набив кучу шишек, представляю мое HowTo:

Как прикрутить FCKeditor к Pylons, пошаговое руководство

Создадим проект, к примеру "myapp":

$ paster create -t pylons myapp
$ cd myapp

Идем на http://ckeditor.com/download и скачиваем последнюю версию FCKeditor. Вероятно, новее уже не будет, потому что разработчики переключились на новые продукты - CKeditor и CKFinder, которые по сути - редактор и менеджер файлов по отдельности. Кстати, другой известный WYSIWYG редактор, TinyMCE, идет подобной дорогой (у него нет поддержки Python, кстати). И я бы выбрал этот новенький, красивенький CKeditor, если бы не одно обстоятельство - разработчики тоже не сделали поддержки для Python. Может быть появится попозже. Может быть я сам как-нибудь займусь и перепишу коннектор для него. Может быть. А пока - продолжим.

Извлечем из архива папку fckeditor в myapp/public/

Создадим шаблон myapp/templates/index.mako вот такого вида:

#coding:utf8
<html>
<head>
    <title>FCKEditor</title>
    <script type="text/javascript" src="/ckeditor/ckeditor.js"></script>
</head>
<body>
<script type="text/javascript" src="/fckeditor/fckeditor.js"></script>
    <form action="" method="post" target="_self">
        <input type='hidden' name='body' id='body' value='Hello World' />

        <script type="text/javascript">
            var oFCKeditor = new FCKeditor() ;
            oFCKeditor.BasePath = '/fckeditor/';
            oFCKeditor.ToolbarSet='Default'
            oFCKeditor.Height    = 300 ;
            oFCKeditor.InstanceName = 'body' ;
            oFCKeditor.Create() ;
        </script>
    </form>
</body>
</html>

Удалим файл myapp/public/index.html
Создадим контроллер index:

 $ paster controller index

В контроллере myapp/controller/index.py в классе IndexController укажем отобразить вышесозданный шаблон:

class IndexController(BaseController):
    def index(self):
        return render("/index.mako")


Пропишем путь в myapp/config/routing.py для корня нашего сайта:

    # CUSTOM ROUTES HERE
    map.connect('/',controller='index',action='index')

Запустим сервер:

$ paster serve --reload development.ini

Теперь в нашем любимом браузере по адресу localhost:5000 видим - редактор уже присутствует. И он работает, получить данные при нажатии кнопки сохранения можно через request.POST['body'].
Вам больше ничего и не надо? Тогда заканчиваем читать здесь. А мне еще нужно осуществить загрузку файлов на сайт и просмотр их на сервере.

Создадим контроллер fckeditor, в который будем направлять запросы редактора на просмотр и загрузку файлов:


$ paster controller fckeditor

Добавим в файл myapp/config/routing.py пути роутинга, чтобы приложение обращалось не к файлам в своем базовом каталоге, а к нашему контроллеру. По умолчанию, в файлах конфигурации FCKeditor все настроено на работу с php.


    # CUSTOM ROUTES HERE
    map.connect('/fckeditor/editor/filemanager/connectors/php/*path_info', controller='fckeditor')
    map.connect('/',controller='index',action='index')

В файле myapp/controllers/fckeditor.py перед объявлением класса добавим путь к нашим файлам Python-коннекторов, идущих в комплекте с FCKeditor, и импортируем из них нужные классы.

import sys
sys.path.append("/media/disk/Projects/myapp/myapp/public/fckeditor/editor/filemanager/connectors/py")
from connector import FCKeditorConnector
from upload import FCKeditorQuickUpload


Также не забудьте удалить или переименовать папку myapp/public/fckeditor/editor/filemanager/connectors/php, иначе пилоны найдут эту папку и предпочтут брать файлы оттуда, игнорируя правило, прописанное в routing.py

Теперь, собственно, класс FckeditorController из myapp/controllers/fckeditor.py

class FckeditorController(BaseController):
    def __call__(self,environ,start_response):
        id=environ['wsgiorg.routing_args'][1]['path_info']
        if id=='connector.php':
            environ['SCRIPT_FILENAME'] = 'connector.py'
            conn = FCKeditorConnector(environ)
        elif id == 'upload.php':
            environ['SCRIPT_FILENAME'] = "upload.py"
            conn = FCKeditorQuickUpload(environ)
        else:
            start_response ("200 Ok", [('Content-Type','text/html')])
            yield "Unknown page requested: "
            yield environ['SCRIPT_NAME']
            return
        data = conn.doResponse()
        start_response ("200 Ok", conn.headers)
        yield str(data)


Для нашего удобства настроим myapp/public/fckeditor/fckconfig.js. Пусть Интерфейс будет русским!

FCKConfig.AutoDetectLanguage    = false ;
FCKConfig.DefaultLanguage        = 'ru' ;

Добавим в настройках development.ini каталог для загрузок и хранения файлов:

[DEFAULT]
static_store = %(here)s/myapp/public/upload

Если вы сами не создадите эту папку - Pylons умница сделает это за вас.
Теперь немного пошаманим в настройках коннектора
myapp/public/fckeditor/editor/filemanager/connectors/py/config.py

Enabled = True
UserFilesPath = '/upload/'
from pylons import config
UserFilesAbsolutePath = config['static_store']+'/'


И наконец, последний штрих - внесем парочку измененеий в файл
myapp/public/fckeditor/editor/filemanager/connectors/py/fckcommands.py
а именно в класс UploadFileCommandMixin:

class UploadFileCommandMixin (object):
    from pylons import request
    # Заменить if self.request.has_key("NewFile"): на
    if request.POST.has_key("NewFile"):
        # Заменить newFile = self.request.get("NewFile", "") на
        newFile = request.POST["NewFile"]

Вот вроде и всё. Теперь на стартовой странице будет виден редактор на русском языке, который может работать с загружаемыми файлами. Надеюсь, кому-нибудь помогут мои мытарства.

2009-10-02

Как подружить Pidgin и Facebook

По состоянию на 1 октября 2009 года, стандартные пакеты из репозитария не позволяют подключаться к Facebook-чату, выдает ошибку соединения или неправильный логин-пароль. Как лечить:
Раз: http://mirror.ne.gov/ubuntu/pool/universe/j/json-glib/libjson-glib-1.0-0_0.7.6-0ubuntu1_i386.deb
Два: http://pidgin-facebookchat.googlecode.com/files/pidgin-facebookchat-1.61.deb
Это просто обновленные пакеты, которых пока нет в репозитариях.
Устанавливаем их по порядку, запускаем Pidgin, создаем аккаунт типа Facebook-чат - и плагин начинает работать. Чудеса!

2009-09-28

Pylons, создание модели в SQLAlchemy

Вот как бывает. Стараешься что-то изучить, потом отвлекаешься, а потом, через несколько месяцев снова смотришь на свой код и думаешь - интересно, а как я это сделал?
Чтобы не забыть, опишу последовательность создания модели в Pylons.

1. Создаем новый проект, назовем его newapp.

$ paster create -t pylons newapp
$ cd newapp

2. В файл ./development.ini добавляем расположение файла базы данных, и указываем (опционально) автоматическую конвертацию в юникод.

sqlalchemy.url = sqlite:///%(here)s/newapp.sqlite
sqlalchemy.convert_unicode = true

3. В файл ./newapp/config/environment.py импортируем модуль алхимии и модель, которую создадим чуть позже.

import sqlalchemy as sa
from newapp import model

Там же, в методе load_environment добавим создание алхимического движка для нашей БД и запустим метод init_model

def load_environment(global_conf, app_conf):
____#.....................................#
____engine = sa.engine_from_config(config, "sqlalchemy.")
____model.init_model(engine)

4. В файле ./newapp/websetup.py импортируем модель

from newapp import model

И здесь же, в метод setup_config добавим строки, необходимые для генерирования базы данных из модели.

def setup_config(command, filename, section, vars):
____#...................................#
____log.info("Creating database tables")
____model.meta.create_all(bind=model.engine)
____log.info("Finished setting up")

5. Создаем модель в файле ./newapp/model/__init__.py

# Импортируем модули, которые могут нам понадобиться

from datetime import datetime
from sqlalchemy import Table, Column, Integer, String, DateTime, MetaData, ForeignKey, orm
meta = MetaData()

# Метод, стартуемый в шаге 3: публикуем алхимический движок и сессию, которую
# создаем для работы с БД с нужными нам опциями, и создаем привязки таблиц и
# классов, в т.ч. по внешним ключам.

def init_model(bind):
____global engine, Session
____engine = bind
____Session = orm.scoped_session(orm.sessionmaker(transactional=True, autoflush=True, bind=bind))
____orm.mapper(Sections,sections)
____orm.mapper(Articles,articles,properties={'section':orm.relation(Sections)})

# Описываем таблицы:

sections=Table('sections',meta,
____Column('id',Integer,primary_key=True,autoincrement=True,nullable=False),
____Column('name',String,default=u'',nullable=False)
)
articles=Table('articles',meta,
____Column('id',Integer,primary_key=True,autoincrement=True,nullable=False),
____# А эта колонка - с внешним ключом
____Column('section_id',Integer, ForeignKey('sections.id'),nullable=False,default=0),
____Column('name',String,default=u'',nullable=False),
____Column('body',String,default=u'',nullable=False),
____Column('created_at',DateTime(),nullable=False,default=datetime.now),
____# Обратим внимание, тут мы добавляем триггер на обновление записи
____Column('updated_at',DateTime(),nullable=False,default=datetime.now,onupdate=datetime.now)
)

class Sections(object):
____def __repr__(self):
________ return self.name.encode('utf8')
class Articles(object):
____ def __repr__(self):
________ return self.name.encode('utf8')

6. Реализуем модель в файл базы данных.

$ paster setup-app development.ini

7. Создаем контроллер ./newapp/controllers/index.py.

$ paster controller index

и добавляем в метод index код для добавления данных в наши таблицы и для извлечения.

section=model.Sections()
article.name=u'Раздел 1'
model.Session.add(section)

article=model.Articles()
article.section_id=1
article.name=u'Статья 1'
article.body=u'Много текста'
model.Session.add(article)

model.Session.commit()

sql=model.Session.query(model.Articles).get(1)
return sql.section # Вывод данных, получаемыех по внешнему ключу

Вот как-то так, если вкратце.
P.S. Чтобы было меньше проблем с кодировками, не лишним будет в начало каждого файла добавлять строку

#coding:utf8

2009-09-04

Чужой среди своих: Linux в windows-домене

Об этом много чего написано, но если чисто-конкретно, то:

Указываем IP, маску подсети и шлюз в /etc/network/interfaces (с учетом, что IP статический):
iface eth0 inet static
address 192.168.xx.xx
netmask 255.255.0.0
gateway 192.168.xx.xx
auto eth0

Прописывем DNS сервера в /etc/resolv.conf (можно несколько):
nameserver xxx.xxx.xxx.xxx
nameserver xxx.xxx.xxx.xxx

Устанавливаем samba:
$ sudo apt-get install samba

Прописывем в /etc/samba/smb.conf доменное имя:
workgroup = DOMAIN

Перезапускаем сеть и samba:
$ sudo /etc/init.d/networking restart
$ sudo /etc/init.d/samba restart

Теперь, для удобства перемещения по сети можно установить удобную утилиту pyNeighborhood и smbfs
$ sudo apt-get install smbfs pyneighborhood

Настроить pyNeighborhood: указать папку для монтрования сетевых ресурсов, логин и пароль в сети, опции монтирования (очень актуальна кодировка, см тут). Остальное можно оставить по умолчанию. Программа проста и работает очень быстро. Особенно выручит она пользователей xfce, т.к. гномовский Nautilus умеет перемещаться по сетевым папкам, а Thunar - нет.

2009-09-02

Если FFmpeg при кодировании ругается на нехватку кодеков

На днях решил перекодировать пару видяшек для PSP жены, воспользовавшись ffmpeg, на что последний отреагировал, разведя руками - не знаю, мол, кодека mpeg4.
Стало ясно, что в системе установлен не полный набор кодеков. Чтобы решить эту проблему, делаем так:

Удаляем полностью ffmpeg и обновляем данные репозитариев:
$ sudo apt-get purge ffmpeg
$ sudo apt-get update

Устанавливаем полные библиотеки кодеков, они попросят удалить предыдущие. ОК.
$ sudo apt-get install libavcodec-unstripped-* libavdevice-unstripped-* libavformat-unstripped-* libavutil-unstripped-* libpostproc-unstripped-* libswscale-unstripped-*

Возвращаем ffmpeg:
$ sudo apt-get install ffmpeg

А вот скрипт, чтобы кодировать avi-шки в формат, который переваривает PSP:

#!/bin/bash
[ -d psp ] || mkdir psp
ffmpeg -i "$1" -f psp -s 368x208 -aspect 16:9 -vcodec mpeg4 -b 500k -acodec libfaac -ab 96k -ac 2 "psp/$1.MP4"

В интернетах встречается подобный скрипт, в котором написано "-acodec aac" - не верьте, будет ругаться.

2009-08-18

MySQL, phpMyAdmin 3, root без пароля и backup.

phpMyAdmin не желает принимать авторизацию без пароля.

Правим файл /usr/share/phpmyadmin/libraries/config.default.php
# Строка 227:
$cfg['Servers'][$i]['nopassword'] = true;
# Строка 363
$cfg['Servers'][$i]['AllowNoPasswordRoot'] = true;

Забыт пароль root и его надо сменить или убрать вовсе.

Гасим MySQL сервер, например так:
$ sudo /etc/init.d/mysql stop
Запускаем его без учета привелегий:
$ sudo mysqld --skip-grant-tables
В консоли mysql вносим необходимые изменения в привелегии:
$ sudo mysql
mysql> UPDATE mysql.user SET Password='пароль_или_ничего' WHERE User='root';
mysql> FLUSH PRIVILEGES;
Перезапускаем сервер.

from sontan.name import this
Создание backup базы данных.

$ mysqldump --all-databases --user=NAME --password=PASS > /home/USER-NAME/sql-dump.sql

--all-databases можно заменить на конкретное имя БД.

Задать кодировку в скрипте:
--default-character-set=charset_name

Чтобы в коде дампа была команда установки кодировки:
--set-charset

И сожмем результат в gzip:
gzip --best /home/USER-NAME/sql-dump.sql

Читаем man mysqldump.

Редактируем текст в Firefox через Vim

Сразу к делу. Для того, чтобы редактировать тексты в полях форм интернет-страниц, для браузера Firefox есть замечательный плагин "It's all text!". Его настройки позволяют задать в том числе и горячую клавишу, что само по себе прекрасно. Представьте - переходите в поле ввода, чтобы отписаться на форуме или в гостевой, нажимаете сочетание клавиш - и пишете в вашем любимом редакторе, а сохраняя текст тем самым отправляете его в браузер. Красота!
Но что, если вы хотите воспользоваться консольным Vim?
При настройке плагина нужно указать полный путь к файлу редактора. Ну и запустим мы Vim. Ну и будет он где-то в бэкграунде. Неудобно! Нужно завернуть vim в консоль.
Хотел бы я воспользоваться таким способом, да только параметры запуска плагин не передает как надо. Что, руки вверх?
На помощь к нам спешит скрипт из трех строк. Я накидал его на питоне, но наверняка можно и десятком других способов. Делаем скрипт исполняемым и в настройках плагина указываем путь к нему. Назначаем горячую клавишу (у меня это Alt-W) и радуемся удобству.

#!/usr/bin/env python
import os,sys
os.system('gnome-terminal -e "vim %s" ' % sys.argv[1])

Или на bash:

#!/bin/bash
gnome-terminal -e "vim \"$*\""

2009-08-12

SSH через http-proxy

Выжимка из этой статьи для конкретной ситуации.
Имеем: Ubuntu 9.04 и анонимный http-proxy (в моем случае Usergate) для выхода в интернет с работы.
Задача: подключиться по ssh к хостингу на masterhost.
Решение:

$sudo apt-get install corkscrew

~/.ssh/config:
Host uXXXXX.ssh.masterhost.ru
ProxyCommand corkscrew proxy_ip_address proxy_port %h %p

Готово.

2009-08-11

Программа для изучения Библии в Linux: добавлен перевод KJV.

Собственно, тема все раскрывает. Теперь в программе есть два перевода - русский Синодальный с апокрифами и King James version без апокрифов.
http://files.mail.ru/GQ0PHF
Особенности:
- поиск английского текста - без учета регистра, русского - с учетом регистра;
- просмотр параллельных мест - по клику на номер стиха;
- выделение текста и клавиша F5 - поиск выделенного фрагмента;
- клик по названию найденного фрагмента - показать весь текст главы;
Есть баг - если смотреть русские тексты апокрифов, потом перейти в английский перевод, закрыть программу и снова запустить - она не откроется, т.к. ищет тексты апокрифов в KJV и не находит. Будет исправлено, пока же просто старайтесь так не делать. В случае чего - удалите файл ~/.Bible.conf и все будет запущено с настройками по умолчанию.

VIM: как назначить запуск скриптов на горячую клавишу

Задача: по нажатию F5 передавать скрипт разным программам, в зависимости от расширения файла (как это реализовано в SciTE).
Вот пара вариантов ее решения. Просто добавим в ~/.vimrc один из этих блоков.

1) Написание функции:

function Run()
let $ext=expand("%:e")
if $ext=="py"
!/usr/bin/env python "%"
elseif $ext=="php"
!/usr/bin/env php "%"
elseif $ext=="html" | $ext=="mako" | $ext=="htm"
!firefox "%"
endif
endfunction
map <F5> :call Run()

Здесь мы получаем расширение файла % через модификатор :e, присваиваем его переменной $ext, после чего по этому признаку решаем, что будем делать с файлом. Потом привязываем вызов функции к горячей клавише F5.

2) Использование автокоманд:

autocmd BufEnter *.py map <F5> !/usr/bin/env python %
autocmd BufLeave *.py unmap <F5>
autocmd BufEnter *.php map <F5> !/usr/bin/env php %
autocmd BufLeave *.php unmap <F5>

Теперь при редактировании скрипта за F5 закреплена команда запуска, а при потере фокуса эта привязка сбрасывается.

Оба способа имеют право на существование, но я остановился на первом.

P.S. Мой .vimrc

2009-07-27

Aptana и тормоза

Краткая заметка для себя.
Устанавливая Aptana, нужно предварительно установить и немного настроить Java:
$sudo apt-get install sun-java6-jre sun-java6-plugin sun-java6-fonts
$sudo update-alternatives --config java
Выбрать пункт 1 (/usr/lib/jvm/java-6-sun/jre/bin/java)
Иначе будет очень тормозить.
Взято с хабра.

2009-07-22

Gedit-плагин для фолдинга (folding)

Вообще-то Gedit - это не текстовый редактор. Особенно для программистов. А тем более на Python.
На самом деле это конструктор. Имеющиеся возможности по созданию плагинов делают его эдаким лего - не хватает какой-либо функции - добавь плагин. Нет нужного - напиши сам и не забудь поделиться с другими. И это хорошо и правильно.
Мне не хватало фолдинга - возможности сворачивать блоки кода для облегчения работы с большими объемами текста. Начало положено!
Что можно: сворачивание выделенного текста и сворачивание по отступам (блоки типа def, if, class и т.п.) по горячим клавишам Alt-Z. Разворачивание по ним-же. Развернуть все блоки - Alt-X
Скачать архив и распаковать файлы в ~/.gnome2/gedit/plugins/

Скачать
P.S. Python 2.6, Gedit 2.26.1

2009-07-20

Материнская плата ASUS M3N78 Pro и глюки в Ubuntu

Вкратце: произошел казус при попытке установки Linux Mint (Ubuntu 9.04) на компьютер с материнской платой Socket AM2 ASUS M3N78 Pro {AM2, nF8300, DDR2 1066, SATA2 RAID, PCI-E, 8-ch Audio, GBL, HDMI, 1394, ATX}
Подробнее. Установка прошла без проблем, как обычно. На первый взгляд все работает, звук есть, видео есть. Ставлю обновления. Соответственно обновляю драйвер видеокарты (встроенная в материнскую плату GeForce) с 173-го на 180-й. Все, полный затык. Виснет и глючит.
Итоги разборок, огорчений и открытий:
Драйвер 180 из репозитариев слишком стар для этой видеокарты и вызывает шок X.
173 кое-как работает, но некоторые вещи отображает некорректно (окно "Параметры" в GIMP, например).
Как лечится. Скачиваем с сайта nVidia самый свежий драйвер.








Устанавливаем его. Переходим в режим консоли (Alt+Ctrl+F1). Логинимся там, и останавливаем гном:
$ sudo /etc/init.d/gdm stop
Находясь в каталоге, куда скачан драйвер, запускаем установку:
$ sudo sh NVIDIA-Linux-x86-185.18.14-pkg1.run
Будут задаваться всякие вопросы, типа прописать ли настройки в x.org - соглашайтесь. После того, как все закончится, перезагрузите машину.
$ sudo reboot
Теперь все станет работать нормально. Если посмотреть в меню утилиту "Драйверы устройств", то там будет показано что используется старый драйвер, однако
$ nvidia-settings
скажет совсем другое - используется самый новый драйвер nVidia. И тут наступает счастье.

И напоследок старый unix-совет: не сломалось - не чини! Помните старый анекдот про программиста и его сына, который спросил "А почему солнце каждый день всходит и каждый вечер заходит?"
- Ты проверял?
- Проверял!
- Каждый день работает?
- Каждый день!
- Тогда ничего не трогай, ничего не меняй.

2009-07-09

Новое знакомство со старым другом: gnome-terminal

Как всегда, то что под рукой - то хуже всего знаешь. А узнаешь только когда приспичит.
Кому не известна стандартная гномовская консоль gnome-terminal? Разве что заядлому GUI-шнику. Этот инструмент служит верой и правдой уже многие годы, стал привычным и... хорошо знакомым?
А началось все с того, что я решил освоить легендарный VIM. И очень мне хотелось сделать для него ярлычок в панели запуска приложений, чтобы не лезть в меню. Чтобы одним кликом запустилась консоль и в ней сразу же vim.

Путь первый.
В окне терминала идем в меню "Правка - Настройки профиля - Заголовок и команда - Запускать другую команду вместо моей оболочки". Ставим галочку, вписываем в строку для команды "vim". Теперь при запуске gnome-terminal вместо приглашения shell сразу же будет запущен vim. Что-ж, это уже неплохо.

Путь второй, усовершенствованный.
В меню "Правка - Профили" создаем новый профиль, назовем его, скажем, "vim", в котором пропишем запуск редактора (см. путь 1). Теперь, чтобы запустить терминал с этим профилем, нужно дать команду:
$ gnome-terminal --window-with-profile=vim
Здорово! А теперь, захотим открыть еще одну вкладку в этом терминале. Угадайте, что в этой вкладке автоматически запустится? Правильно, он, родимый. К пути 1 это тоже относится.

Путь третий, продолжаем расти.
Не будем плодить профили, если, конечно, вам не нужны особые расцветки в разных окнах консоли. На этот раз мы используем стандартный профиль, но запустим vim так:
$ gnome-terminal -e vim
Кидаем ярлычок на панель запуска приложений и радуемся. Теперь чуть-чуть его доработаем: нам ведь не нужна панель меню вверху? Да и хорошо бы его на весь экран сразу развернуть, и рабочую директорию задать, чтоб удобнее было.
$ gnome-terminal -e vim --hide-menubar --geometry=1280 --working-directory=/home
Неплохо, верно? Просто указать параметры запуска, и всего делов.

Путь четвертый: совершенство.
Наконец, мне захотелось, чтобы по одному клику открывалась консоль с двумя вкладками, в одной из которых будет vim, а во второй mc, чтобы удобнее было с файлами управляться. Вот, что у меня получилось:
$ gnome-terminal \
--tab-with-profile=Default \
--working-directory=/home/kawaikunee/Проекты/ \
--title=MC \
-e mc \
--tab-with-profile=Default \
--working-directory=/home/kawaikunee/Проекты/ \
--title=VIM \
-e vim \
--hide-menubar \
--geometry=1280
Что мне и требовалось. Остается нажать на F11 чтобы ничто не отвлекало от процесса созидания очередного шедевра. Дерзайте!
P.S. Помощь в понимании вопроса оказана man gnome-terminal

2009-07-06

Linux Mint: долой болтливых животных!

У кого установлен Linux Mint по умолчанию, тот при запуске терминала перед строкой приглашения видит некую заумную фразу на английском языке, которую якобы цитирует одино из нескольких видов животных: олень (или лось?), корова, пингвин, и вроде кто-то еще.
Поначалу прикольно, а потом достает. Как избавиться от этого?
sudo gedit /etc/bash.bashrc
Удаляем или комментируем последнюю строчку, примерно такую:
# /usr/bin/mint-fortune
Больше животные в консоли вас не потревожат.

2009-07-03

Pylons, несколько ньюансов.

Изучаю питоновский веб-фреймворк Pylons. На английском языке полно официальной документации к его компонентам, на русском же бедновато. Так как присутствует несколько самостоятельных кирпичиков, приходится изучать сразу в нескольких направлениях. Хорошо джангистам, у них один DjangoBook на все случаи жизни. А тут и paste, и mako, и sqlalchemy, и webhelpers, и вообще невпроворот всего, и у каждого своя документация. А потом надо по доке Pylons учесть ньюансы их взаимодействия. Иногда мозг вскипает, пока сообразишь как и что. Чтобы не позабыть находок, что были сделаны в процессе исследования, немного о них расскажу.

Работа с базами данных.

По умолчанию, в Ubuntu пилоны комплектуются библиотекой sqlalchemy, хотя можно использовать sqlobject или вообще не использовать ничего, кроме стандартного db-api. Я не стал ничего менять - алхимия так алхимия.
Построение модели в докуметации пилонов описано так: создаем описания таблиц, потом классы, потом привязываем одно к другому и определяем отношения между ними. Сайт SQLAlchemy предлагает вариант совмещения этого в одном определении класса. Можно и так и эдак, но вот чтобы из определения таблиц создать реальную схему в базе данных путем "paster setup-app development.ini" второй способ не самый лучший. У меня они не создавались ни в какую, только первый пилоновский метод дает ожидаемый результат. Зато если таблицы создавать вручную, мне больше понравился именно способ sqlalchemy, получается компактнее как-то, все в кучке.

Теперь дальше. Использование SQLite и MySQL проблем не вызвало. Но по работе мне потребовалось коннектить приложение с MSSQL Server 2005, а это уже куда интереснее. Не буду вдаваться в подробности, просто сразу дам совет: используйте ODBC. Модуль python-mssql время от времени падал с ошибкой, а вот pyodbc повел себя молодцом. Поэтому в файле development.ini, раздел [app:main], нужно прописать соединение с MSSQL через ODBC, используя модуль pyodbc:

sqlalchemy.url = mssql://user:password@host\instance/dbname
sqlalchemy.module_name=pyodbc

Именно так. Кто не понял, что такое instance? Это имя установленного сервера. В 2005 Express версии оно SQLEXPRESS по умолчанию. Остальное должно быть понятно.
Теперь дальше. Угадайте, в какой кодировке отдает данные этот сервер? Правильно, в cp1251. А нам надо в какой? Конечно, unicode. Там же:

sqlalchemy.encoding='cp1251'
sqlalchemy.convert_unicode = true

В документации по SQLAlchemy, в разделе API Reference есть еще несколько параметров.

Роутинг.
Тут пара ньюансов. Там, где в Ubuntu map.connect('',controller="index",action="index"), в Windows версии '' пришлось заменить на '/', загадочно это конечно, но вот у меня так. Иначе ошибка.
И там, где в Linux:
map.connect("/:controller/:action/:id")

в Windows:
map.connect("/{controller}/{action}/{id}").
Тоже какая-то тайна тут кроется...

Шаблоны Mako. Чудесная штука. Есть две вещи, о которых я должен упомянуть.
Во-первых, это отвратительная реакция редакторов и IDE на теги <%. Об этом я писал чуть раньше. Кстати, в Windows второй из описанных способов не работает, не знаю почему.
Во-вторых, мне хотелось, чтобы если в шаблоне указанная переменная отсутствует, то показывалась бы пустая строка на ее месте, а не ошибка. Вот два пути:
Этот я нашел где-то в сети, но мне кажется, он не работает как надо, в начале шаблона ставить такой блок:
<%!

UNDEFINED=''

%>
А этот более кардинальный. В файле /config/environment.py, в функции load_environment добавить:
config['pylons.strict_c'] = False


В версии 1.0 эта строка выгладит как
config['pylons.strict_tmpl_context'] = False

И ошибки нехватки переменных в шаблоне как рукой сняло.
Пока что все. У кого есть толковые советы - милости прошу.

2009-06-25

Работа с образами дисков (в том числе PlayStation)

Не раз наблюдал, как люди ищут и спрашивают аналоги привычных в Windows программ в мире Linux. Много, много альтернативного софта может предложить пингвиниус, но вот разобраться в этой куче - с полпинка не получается.
Не так давно захотелось поиграть в Final Fanasy VIII, вспомнить молодость ^_^
Диски есть, а вот торчать у телевизора не хочется; да и такие вещи, как играть до опупения (т.е. до ближайшей сохранки) меня не радуют. Чтобы надоело - сохранился и выключил. Все это позволяют эмуляторы PlayStation. Их несколько штук, я использую pSX, он прост в настройках. Но тема не об этом.
Вопрос: как сделать из дисков PS образы для эмулятора? В Windows пользователю потребовалось бы проделать примерно такой путь: найти в сети Alcohol 120%, потом кряк для него, потом создать образы. Мы же так не делаем и никому не советуем.
Наконец к делу: вам нужен AcetoneISO. Он умеет делать чудесные вещи с дисками и образами. Меня выручил как нельзя вовремя, у него есть опция по созданию iso PlayStation (раздел ImageConversion). Спасибо, господа разработчики!

2009-06-24

SciTE и шаблоны mako (mako templates) для Python

Несмотря на то, какой гибкий редактор этот SciTE, я обнаружил в нем заковыку, с которой боролся пару дней. Дело в том, что когда используешь его для создания шаблонов на движке mako (используется во фреймворках типа Pylons и сам по себе), то всё после тега типа <%include>, <%def> и т.п. будет подсвечено одним болотным цветом. Редактор считает это началом блока ASP. Цвет видимо подходящий...
Долгие поиски и копания в гугле и файлах .properties были неутешительны. Во-первых, эта проблема не только SciTE (Scintilla), но и других редакторов и IDE, и я нашел только один, который игнорировал эту засаду - обычный gEdit. Во-вторых, несмотря на гибкость, обработчик лексеров все-же изменить правкой конфигов нельзя, это вшито в программу, и придется очень глубоко вникать, изменять, пересобирать...


Вот простой путь, для тех, кто хочет использовать SciTE и при этом видеть нормальную подсветку синтаксиса: после каждого тега mako добавляйте конструкцию:
<!--%>-->
Она скажет редактору, что блок ASP закончен, и можно продолжать обрабатывать HTML код. При этом, из-за html-комментариев, закрывающий тег на странице виден не будет.


Второй вариант - более глобальный поначалу, но зато намного упрощающий жизнь потом. Я ковыряю Pylons, поэтому покажу, как это делается там:
В файле /config/environment.py вносим дополнительно:

def load_environment(global_conf, app_conf):
.......... содержимое функции ..........
tmpl_options['mako.preprocessor']=mako_replase_tag_to_my
def mako_replase_tag_to_my(s):
return s.replace('<mako:','<%').replace('</mako:','</%')

После этого в шаблонах вместо <% пишем <mako:, а вместо </% пишем </mako:
Уф. Ну и намучился я с этим. Но Слава Богу!

2009-06-23

Программа для изучения Библии в Linux. Часть 3.

Продолжается работа над программой для работы с текстами Священного Писания под Linux.
На сегодня (26.06.2009) предлагается версия 0.3: http://files.mail.ru/9A2QKM
В зависимостях шрифты от MS, чтобы отображалось все, как задумано.
Просмотр текстов, поиск, как обычный так и путем выделения слова и нажатия кнопки с буквой "f". Получения списка параллельных мест при клике мышью на номер стиха в основном окне. Получение текста главы по клику мышью на название книги в поле результатов поиска. Сохранение книги, главы и фразы поиска текущего сеанса. Скриншот в предыдущем посте.
А вот так выглядит программа на экране моей Nokia N810. Я планирую сделать deb-пакет и для этой планшетки.

2009-06-19

И все-таки SciTE!

Некоторое время назад, когда писал о стандартном редакторе файлов Gnome, я упомянул о SciTE. Писал, что сложно настроить человеку, привыкшему к GUI, и с кодировками проблемы... Хотя пользовался им довольно долго. Но польстился на модули и расширения gedit. А недавно на глаза снова попалась информация о SciTE, о настройке и возможностях этой чудесной программы.
Разные люди бывают. Кому-то хочется чтобы установил и стал работать. Кого-то хлебом не корми, а дай только поковыряться в настройках и конфигурационных файлах. SciTE позволяет и то, и другое. И я вернулся.
Прежде всего - он использует Scintilla, тот-же движок, что и небезызвестный Notepad++. Стандартные установки вполне позволяют сразу начать программировать, к примеру, на python. Поддерживает просто массу языков. И для любителей все настраивать - это находка. Когда я читал перевод документации - то понял, что gedit все-таки еще не дорос...
Настоятельно рекомендую! Не поленитесь прочитать:
Документация SciTE

2009-06-18

Программа для изучения Библии в Linux. Часть 2.

В одном из предыдущих постов я упоминал о пишущейся программе для изучения Библии в Linux. Разобравшись с упаковкой вышеупомянутого в deb-пакет, наконец-то создал готовое к употреблению блюдо. Если что-то будет не так - строго не судите, это супер-пупер альфа, и вообще, судить нехорошо. Тестировалось на Ubuntu 8.10 и 9.04.
Вот что мы имеем на начальном этапе: http://files.mail.ru/45YLQ0

UP
Этап 2: http://files.mail.ru/A5XDRT
Этап 3: http://files.mail.ru/OP5535

2009-06-14

Подключение Стрим ТВ. Последовательность действий.

В процессе подключения этой услуги от Стрима возникают некоторые вопросы, и все не так очевидно и просто, как хотелось бы. Я опишу последовательность действий и проблемы, с которыми я столкнулся, может быть, поможет хоть кому-нибудь. Когда я искал, подробной инструкции не встретил.
Итак, подключение Стрим ТВ возможно или с вызовом мастера на дом (тогда вам больше ничего не потребуется, только банальные деньги). Кроме того, если вы живете за кольцом, то придется выложить 600 р только за то, что вы неудачно выбрали место жительства. За каждый метр прокладываемого по дому кабеля с вас возьмут 60 р. Итого, в моей ситуации, когда нужно в Зеленоградской квартире провести 25м кабеля в другую комнату, все это выливается в приличную сумму. Вывод: обойдемся своими силами.
В конторе Стрима берем в аренду тв-декодер. Там же есть сетевые кабели, но максимум 15 м. - не мой вариант. Наверняка еще и дорого, но я не спрашивал. Кабель покупаем в компьютерном магазине (в Компстаре нам обжали 25 м витой пары меньше чем за 300 р) или берем у знакомых сисадминов.
Модем должен иметь несколько LAN интерфейсов. У меня - Echolife HG520 с 4-мя. Для подключения телевидения предназначен LAN-2. Итак, барабанная дробь: включаем в него сетевой шнур, тянем-потянем по квартире до тв-декодера, включаем все по инструкции, и видим на экране телевизора шедевр Малевича с надписью "Loading...". Это неправильно, значит, все не так просто...
В чем причина? Дело в том, что Стрим ТВ не позволит вашему модему динамически раздавать IP-адреса, когда он работает в режиме роутера (как было у меня). Поэтому, чтобы телевидение успешно начало работать, выполняем следующие действия.
1) В управлении модемом (в браузере набираем 192.168.1.1, логин и пароль по умолчанию "admin") в разделе "Base - DHCP" Выключаем DHCP (DHCP = None, Submit).
2) В настройках сетевых соединений компьютеров, выходящих в интернет, нужно указать статические IP типа 192.168.1.x, где x - от 2 до 255. Маска подсети - 255.255.255.0, шлюз - 192.168.1.1, адреса DNS - 212.188.4.10, 195.34.32.116.
3) Звоним в службу поддержки Стрим ТВ, и сообщаем о том, что подключили услугу. Они производят шаманские манипуляции и увеличивают скорость, чтобы телевидение не тормозило.
После этого все должно заработать как часы. Жаль, что этого не указывают сразу в какой-нибудь прилагающейся документации или в личном кабинете, и нужно сначала устроить допросы с пристрастием сотрудников службы поддержки Стрим.

P.S. Были и еще проблемы, и звонил я много раз, но это уже чисто мои сложности, из которых я вынес один вывод: телефонный шнур от щитка до модема ДОЛЖЕН БЫТЬ ИСПРАВЕН, и всякие там кое-как скрученные лапшовые проводочки могут привести к значительному снижению стабильности работы как интернета, так и телевидения. Мои регулярные обрывы соединения исчезли без следа, когда я уладил вопрос с еле-держащимися скруточками за шкафом.
Удачного ТВ!

2009-05-18

Python и аутентификация в Windows-домене

Собственно, задача: компьютер в Windows-домене, на нем есть некий сервер, при обращении к которому он должен определить, зарегистрирован ли представившийся пользователь в домене. Для этого нужно иметь определенный инструментарий, и у нас он есть. Я использую ActivePython 2.6 от ActiveState, там всё комплекте.
[ файл win32test.py ]
-----------------------------------------------------------

# -*- coding: utf-8 -*-

import win32security
import win32net
import win32netcon

def authentication(user, password, domain):
"""
Аутентифицировать пользователя в домене
user - Имя пользователя в домене
password - Пароль пользователя
domain - Имя домена
"""
try:
htoken = win32security.LogonUser(
user, domain, password, win32security.LOGON32_LOGON_NETWORK,
win32security.LOGON32_PROVIDER_DEFAULT
)
if htoken:
return u"Пользователь %s успешно зарегистрирован в домене %s " % (user,domain)
except win32security.error, err:
return u"Номер ошибки: %i\nОшибку вернул %s\nОшибка: %s" % (err[0], err[1], err[2].decode('cp1251'))
except:
return u"Пользователю %s не удалось зарегистироваться в домене %s " % (user,domain)

print authentication("Kawaikunee","secretpassword","DOMEN")

def existuser(user, server, verbose=0):
"""
Проверить существование пользователя в домене.
user - Имя пользователя в домене
server - Имя Domain Controller NetBIOS. Можно указать DNS
verbose - Флаг, печатать ли информационное сообщение
"""

try:
users = win32net.NetUserEnum(
server, 0,
win32netcon.FILTER_NORMAL_ACCOUNT, 0
)
"""
users[0] - список словарей пользователей домена в Unicode, в формате
[{'name', u'Username1'},{'name', u'Username2'},{'name', u'Username3'}]
users[1] - их общее количество
"""
print users[0]
except win32net.error, err:
if verbose:
return u"Номер ошибки: %i\nОшибку вернул %s\nОшибка: %s" % (err[0], err[1], err[2].decode('cp1251'))
else:
return None
for userinfo in users[0]:
if user.decode('utf8').lower() == userinfo['name'].lower():
return u"Такой пользователь существует: %s" % user
print existuser("Kawaikunee","192.168.1.1",1)

-----------------------------------------------------------

Вот такой пример кода. Программирование - это творчество, и оно сродни поэзии. Вот так бы это описал, возможно, какой-нибудь древнерусский сказитель:

Ой ты гой еси, server-батюшка,
Ты скажи-расскажи, не утаивай!
Есть ли в списках твоих добрый молодец,
Что по логину user захаживал?

Отвечал скрипту server ласково:
Посмотри-ка милок, весь мой списочек
Молодыми да острыми глазками.
Да и выбери, кто тебе надобен.

Ну а коли ты в гости надумаешь,
То password отведет стражу лютую.
Заходи скрипт-python, в светлу горницу,
Будем мы разговор разговаривать.

2009-05-07

Открываю Gedit

Кто из программистов не искал для себя идеальный редактор кода? А сколько их развелось на свете! Платных и бесплатных, IDE и простых, под разные OS, просто глаза разбегаются.
И я не избег этой участи. В итоге из IDE первое место в моем багаже прочно заняла Aptana, ну а из простых...
Кто-то пользуется vi или emacs и вполне доволен. А некоторые привыкли в GUI-редакторам и отучить их уже сложно. Вот возьмем, к примеру, меня. Однажды я набрел на SciTE, и был впечатлен: писать в нем в целом неплохо, но вот настройки - это надо знать, что менять в конфигурационых файлах, как прописывать. С кодировкой cp1251 вообще практически никак, а иногда без нее не обойтись. Пользовался им за простоту и легкость, но самое прекрасное - это кнопка F5, по которой выполняется код открытого документа и выводится результат.
А кто из пользователей Gnome не знает такого замечательного приложения, как "Текстовый редактор" gedit? Эта программа проста и незатейлива, годится лишь чтобы изредка поправить конфигурационный файл... так кажется на первый взгляд.
Вся прелесть кроется в его плагинах. Среди них есть поистине шедевры. С их помощью можно легко реализовать клавишу F5 из SciTE - и это только поверхность айсберга. Установите пакет gedit-plugins (входит в стандартный репозитарий Ubuntu, но по умолчанию не установлен) - и посмотрите в Gedit "Правка - Параметры - Модули". Обширное поле для деятельности! О модулях можно прочесть, если нажать в этой вкладке кнопку "Справка", поверьте, это того стоит. Наиболее впечатляющими выглядят "Фрагменты текста" и "Внешние инструменты". Да и в "Правка - Параметры" тоже можно пройтись по чекбоксам, и сделать среду еще более приятной для работы.
Нужны пояснения и подробности? Если будет интересно - напишу еще, но думаю, что вы разберетесь и сами. Поверьте, ничего сложного - творите с удовольствием!

2009-05-05

Чистка файлов на хостинге от сторонних включений с помощью связки grep+sed

Вот уже который раз на хостинге наблюдаю работу некоего зловреда, который включает в файлы сайтов, в названии которых есть слова "main", "index" и "default" сторонний код, подгружающий на компьютеры посетителей зараженные файлы с использованием iframe. Пользователей Linux это не касается, поэтому они могут спать спокойно, для них этот код означает просто очень долгую загрузку страницы, связанную с загрузкой в кэш зараженного файла. Зато пользователи Windows, особенно бороздящие просторы интернета с помощью (если это так можно назвать) IE, подвергаются атаке по полной программе. Я об этой заразе узнал от такого пользователя. Много файлов, много строк, поди найди там всё!
Приступим к решению!
1) Подключаемся к серверу по протоколу ssh и получаем командную строку.
2) Проверяем наличие бяк в файлах php и html, получив список файлов с внедренным кодом (одной строкой):
find . -name '*.php' -o -name '*.html' -exec grep -l -E '^<iframe src=.+></iframe>$' '{}' \;
3) Массово заменим эти включения на пустоту (одной строкой):
find . -name '*.php' -o -name '*.html' -print0 | xargs -0 sed -i -e 's/^<iframe src=.*><\/iframe>$//g'
Конечно, это все временное решение, но хотя бы до следующей атаки пользователи не будут страдать.
Если у кого-то на хостинге случилось подобное, расскажите как боролись!

2009-04-29

Ubuntu 9.04 на Acer Aspire One

Установил с USB, который создал утилитой, идущей в комплекте. То есть сначала установил на дескотоп, посмотрел-повертел, остался доволен. Потом создал флешку, и - Ubuntu 9.04 встала на мой нетбук как влитая, все заработало из коробки, никаких бубнов не потребовалось. Только кардридер не захотел карту читать, пока я не загрузил машинку с воткнутой картой памяти. И жаль, что раздел home у меня был не на отдельном диске, пришлось бэкапить и потом восстанавливать. Теперь-то я сделал по умному. Пара моментов, которым я удивился:
1) Не работает Ctrl-Alt-Backspace, разработчики отключили это сочетание клавиш, непонятно почему. Вернуть, думаю, труда не составит. Забиндить на эти клавиши команду, к примеру "/etc/init.d/gdm restart".
2) При установке на десктоп был предложен вариант автологина первого пользователя, т.е. при включении гном грузится сразу автоматически под юзером. Когда я устанавливал с флешки - такого варианта мне не предложили. Странно, а хотелось бы.
Из прочитанных мной отзывов стало ясно, что если обновлять систему с предыдущих версий - лезут глюки, а если ставить начисто - то работает лучше и быстрее чем 8.10. Что, впрочем, и верно.
P.S. Также по умолчанию стоит Python 2.6, а не 2.5, что тоже порадовало.

2009-03-25

IIS и Python

Чтобы подружить IIS (у меня 5 версия, но думаю, и на поздних всё также) и Python, и заставить файлы с расширением .py обрабатываться интерпретатором, нужно:
1) Если еще не создали, то создать виртуальный каталог, например test
2) Открыть свойства виртуального каталога и перейти во вкладку "Виртуальный каталог".
3) В пункте "Разрешен запуск" должен быть разрешен запуск сценариев.
4) Правее этого пункта жмем на кнопку "Настройка". Там нажимаем "Добавить".
5) В графе "Исполняемый файл" должно быть примерно так:
"C:\Python26\python.exe" -u "%s"
6) Расширение установим как .py
7) Пусть галочки "Обработчик сценариев" и "Проверка наличия файла" будут включены.
8) Теперь осталось только нажать ОК.

Не забудьте, что питоновый файл должен начинаться с того, что указывается правильный заголовок. Примерно так:
[ файл python.py ]

# -*- coding: utf-8 -*-

print 'Status: 200 OK'
print 'Content-type: text/html; charset=utf-8;'
print
print """
Работает!
"""

Теперь, если в адресной строке браузера набрать http://localhost/test/python.py то мы увидим слово "Работает!".

2009-03-24

Полезности

В этой статье я буду собирать всякого рода полезности при работе в консоли, которые мне будут попадаться на глаза. Если захочется сказать "А, я знаю откуда ты это взял!" - не надо. Конечно же не сам придумал.

Вход более одного пользователя в систему с графическим интерфейсом
Для начала переходим в другую консоль, чем стандартная седьмая: Ctrl-Alt-F(1-6). Водим логин и пароль. Теперь мы вошли как второй пользователь в системе. Переходить в другие консоли можно c помощью сочетания клавиш Alt-F(1-7) Чтобы получить графическую оболочку, введем команду:
startx -- :1

Дефрагментация базы данных MySQL
В ходе изменений в структуре БД и информации в ней происходит фрагментирование данных. Дефрагментация выполняется командой:
mysqlcheck -o имя_базы_данных -u пользователь_бд -p пароль_бд
И вообще man mysqlcheck расскажет еще много интересного.

Поиск в мануалах
Иногда знаешь что надо найти, но не знаешь, где искать. Команда man позволяет воплотиться такой дикой мечте:
man -k ключевое_слово
Ну и стандартный метод поиска в открытом мануале - используем клавишу / и сразу за ней - искомое слово, Enter. Чтобы найти следующее вхождение этого-же слова, жмем клавишу n.

Узнать, какой процесс использует примонтированный носитель
lsof +D /media/имя_устройства

Закрыть все приложения, использующие примонтированный носитель
fuser -km /media/имя_устройства

Массовое конвертирование кодировки текста
Скорее всего, вам известно, как весело в Windows переводить текстовые файлы из одной кодировки в другую. Открыл в редакторе, сохранить как, повторять до изнеможения.
Linux открыл для меня прелесть утилиты enca. Поэтому
sudo apt-get enca
После этого текст в ненашей (не utf-8) кодировке приводится в норму так:
enconv *.txt

Массовая замена текста в файлах
Заменить один текст на другой в файлах указанного каталога (включая подкаталоги):
find . -name '*.txt' -print0 | xargs -0 sed -i -e 's/это_заменить/на_это/g'

Многое взято отсюда.

2009-03-17

Python и удаленный Microsoft SQL Server 2005

Для работы из Python с удаленным сервером MSSQL 2005 понадобится провести некоторую подготовку на обоих концах этого тандема.

На стороне сервера баз данных делаем так:
Пуск - Все программы - Microsoft SQL Server 2005 - Средства настройки - Настройка контактной зоны SQL Server. Далее внизу ссылка "Настройка контактной зоны для служб и соединений". В левой панели в первой вкладке видим такие параметры, как "Database Engine", а в нем "Служба" (ставим "Тип запуска" = "Авто" и "Состояние службы" = "Запущена") и "Удаленные соединения" (ставим "Локальные и удаленные соединения").
Ниже Database Engine есть параметр "SQL Server Browser" - "Служба" (ставим тип запуска - "Авто" и состояние службы - "Запущена").
При запуске "Среды SQL Server Management Studio Express", в окошке "Соединение с сервером" будет поле "Имя сервера". Оно выглядит как ИМЯ_КОМПЬЮТЕРА\ИМЯ_СЕРВЕРА_БД. Запомним эти данные, они пригодятся.

На стороне нашего компьютера с Ubuntu:
sudo apt-get install python-pymssql
Вот и всё. Теперь краткий пример работы с БД:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Импортируем библиотеку для работы с MSSQL
import pymssql

# Соединение с БД. Если вы не в том-же домене, что и сервер БД, то вместо
# ИМЯ_КОМПЬЮТЕРА впишите его IP.
con = pymssql.connect(host='ИМЯ_КОМПЬЮТЕРА\ИМЯ_СЕРВЕРА_БД', user='ПОЛЬЗОВАТЕЛЬ_БД', password='ПАРОЛЬ_ПОЛЬЗОВАТЕЛЯ_БД', database='ИМЯ_БД')

# Создаем курсор для работы с соединением
cur = con.cursor()

# Выполняем запрос
cur.execute("SELECT somefield FROM dbo.sometable;")

# Прокручиваем все записи из запроса
for i in cur.fetchall():

   # Данные в БД в кодировке cp1251, поэтому сначала переводим их в юникод
   i=unicode(i[0],'windows-1251')

   # А затем напечатаем их в utf-8 кодировке
   print "%s" % i.encode('utf-8')

# Подтверждаем транзакцию и закрываем соединение
con.commit()
con.close()

По сравнению с тем, как организовать такое соединение из php (через odbc, используя freetds) - просто праздник какой-то!

2009-03-03

Рисуем почтовую марку в GIMP


Заметка, скорее всего, только для себя. Потребовалось для стенгазеты на 8 марта нарисовать большую марку с фотографией весны на ней. Что делаем:
1) Доводим саму картинку до нужной кондиции (размер, цвета, яркость и т.п.).
2) Идем в меню Изображение - Размер холста и увеличиваем его процентов на 10-15, после чего жмем на кнопку "Центр", чтобы наша картинка получилось как бы в белой неширокой рамке.
3) Потом берем инструмент "Ластик", обычный круглый, и примеряем его к краю, чтобы половинка ластика задала как-бы половину ответстия линии отрыва марки (надеюсь вы понимаете, о чем я).
4) После этого чуть ниже палитры кистей находим параметр "Интервал" и увеличиваем его, скажем, до 150, чтобы линия, рисуемая ластиком, была не сплошная, а пунктирная.
5) Ставим край ластика на белую рамку вокруг рисунка, где начнется линия отрыва марки, делаем первый клик. Потом, нажав Shift поставим конечную точку. И так 4 раза по краям нашей марки.
В завершении, можно добавить легкую тень вокруг марки, чтобы добавить объема (Фильтры - Свет и тень - Отбрасываемая тень). Смещение по X и Y пусть будет нулевым. Поэкспериментируйте!

2009-03-02

Несколько решений, пригодившихся мне в последнее время.

Prism через прокси-сервер.
Находим в файле /usr/share/xulrunner/greprefs/all.js строки с настройками network.proxy. Мне понадобилось изменить 5 строк после 720-й.
pref("network.proxy.type", 1);
pref("network.proxy.ftp", "IP_PROXY_SERVER");
pref("network.proxy.ftp_port", PORT_PROXY_SERVER);
pref("network.proxy.http", "IP_PROXY_SERVER");
pref("network.proxy.http_port", PORT_PROXY_SERVER);
Меняем IP_PROXY_SERVER и PORT_PROXY_SERVER соответственно на свои данные.

Midnight Commander не сохраняет настройки.
Обнаружил, что файл ~/.mc/ini не позволяет сохранять данные - нет прав. Что-ж, поменяем их так, чтоб наверняка:
sudo chown ваш_логин ~/.mc/ini
sudo chgrp ваш_логин ~/.mc/ini
sudo chmod 664 ~/.mc/ini
Теперь все будет в порядке.

Эмулятор PlayStation pSX на Acer Aspire One (Ubuntu 8.10).
Возникают проблемы со звуком. Сначала он вообще не запускается и пишет сообщение об ошибке. Решается отключением pulseaudio:
sudo /etc/init.d/pulseaudio stop
killall pulseaudio
После этого начинает работать но страшно дергается - терпеть дольше 10 секунд невозможно. Выдает в консоли что-то вроде sound: underrun. Решается изменением параметра Latency в ~/.pSX/psx.ini, секция [Sound], строка 167. Значения 128 достаточно для корректно работающего звука. Вообще этот эмулятор чрезвычайно простой в настройке, есть русский язык, сохранение по горячей клавише иногда очень кстати.

2009-02-26

Программа для изучения Библии в Linux

Наверняка каждый верующий человек, имеющий в хозяйстве компьютер, так или иначе пользовался различными приложениями христианской тематики. Для работающих в Windows существует даже некоторый выбор. Я использовал долгое время BibleQuote ("Цитата из Библии") Тимофея Ха.
Для русскоязычных линуксоидов же дело обстоит несколько хуже. Тут, насколько я знаю, всего пару вариантов: или запускать что-то из-под wine (ту же BibleQuote например, вроде работает нормально), или устанавливать GnomeSword(Gnome)/BibleTime(KDE). В GS есть модули с русскими текстами, но они с ошибками, некоторые слова сливаются в одно... Нехорошо. В BT - не знаю, не видел, т.к. gnomeшник.
Итак, принято решение: объединить нормальный перевод текстов из Цитаты и GTK+ и создать еще одно приложение для изучения Библии с возможностями, которые посчитаю полезными. Тексты будут храниться в SQLite, программа пишется на Python, интерфейс рисуется в Glade.
Пока примитивно, но основные функции уже есть: выбор, чтение, поиск, отделение ВЗ и НЗ, отключение Апокрифов.
Кому надо - пишите в комменты или в личку.

2009-02-16

Монтирование папки Windows удаленного компьютера

Сегодня увидел, что все еще есть люди, которые этого не знают. Впрочем, я тоже не знал, пока не докопался. Мало ли, у кого-то карма не позволяет нагуглить эту информацию, так пусть ее будет побольше!

Шаг 1. Создаем папку, куда будем монтировать удаленный каталог, пусть это будет /media/nfs:
sudo mkdir /media/nfs

Шаг 2. Устанавливаем поддержку samba-файловых систем
sudo apt-get install smbfs

Шаг 3. Пишем вот такую команду (или делаем алиас в файле ~/.bashrc):
sudo mount -t smbfs //192.168.0.2/ShereFolder /media/nfs -o username=UserName/DomenName%Password,iocharset=utf8,rw,file_mode=0777,dir_mode=0777
где меняем 192.168.0.2, ShereFolder, UserName, DomenName, Password на свои.

И всё. На рабочем столе появится ярлык нового диска. Если вы администратор на удаленной машине с Windows, то можно подключить и не расшаренные папки, а сразу диск, например //192.168.0.2/d$. Очень удобно!

2009-02-12

Виртуальный компьютер: Легко! Быстро! QEMU!

Расскажу немного об этом замечательном эмуляторе. При желании в интернете и man qemu можно найти намного более полную информацию, но мне хочется поделиться "быстрым стартом". Вычитал в LinuxFormat 2006 года и сделал некоторые добавления.

Установка QEMU и его ускорителей:
sudo apt-get install qemu kqemu-common kqemu-source

Создание образа для жесткого диска размером 5 гигабайт (пусть это будет ~/newos):
qemu-img create -f qcow2 newos 5G
ВНИМАНИЕ!
В разных источниках предлагают также вариант создания через dd:
dd if=/dev/zero of=~/newos count=5G
Я пробовал использовать дважды, и оба раза он поглощал все свободное место на /home.
Кто не знает, в чем дело, лучше не рисковать, и использовать qemu-img.

Запуск и установка ОС с CD:
Вставляем диск с операционной системой. Далее
sudo qemu -cdrom /dev/cdrom -hda ~/newos -boot d
(-boot d - для того, чтобы загрузочным диском 1 очереди стал cdrom. Возможны варианты - "c" - жесткий диск, "a" - с флоппи, "n" с сетевого устройства)
Устанавливаем систему как обычно, вы это не раз уже делали.

Запускаем виртуальную машину, от сердца отрываем ей аж 256 мб оперативной памяти, и указываем брать время из нашей реальной машины:
qemu -m 256 -hda ~/newos -localtime
По умолчанию будет дано 128 мегабайт оперативки - что маловато. Также так просто драйверы kqemu не будут работать, и вы получите вот такое сообщение:
"Could not open '/dev/kqemu' - QEMU acceleration layer not activated: No such file or directory"
Избежать ошибки можно либо запуская qemu от имени root, либо дав файлу /dev/kqemu права на чтение для всех.

Сохраняем состояние загруженной ОС:
Переходим в консоль QEMU сочетанием клавиш Ctrl+Alt+2 и пишем
savevm /newos.state

Загрузка сохраненного состояния также из qemu-консоли
loadvm /newos.state
Выход из консоли - Ctrl+Alt+1

Можно начинать эксперименты над разнами дистрибутивами, не ломая свое настроенное хозяйство.
Мммм.. Ну да, есть конечно еще VirtualBox и VMWare, и кто-то будет их отстаивать. Не стану спорить. Но лично мне по душе простота QEMU.