FastNetMon

Показаны сообщения с ярлыком Python. Показать все сообщения
Показаны сообщения с ярлыком Python. Показать все сообщения

понедельник, 29 ноября 2010 г.

Разбор YAML в Python на Centos 5.5

Формат YAML крайне удобен для всевозможных конфигов, причем, его удобно как редактировать вручную (не верите? Посмотрите примеры ниже!), так и разбирать программно, что делает его лучшим другом любого системного администратора :)

Устанавливаем библиотеку для разбора Python формата:
yum install -y PyYAML

Вот пример использования библиотеки:
#!/usr/bin/python

import yaml

document = """
  servers1:
    - host1
    - host2
  srver2:
    - hosta
    - hostb
"""
print yaml.dump(yaml.load(document))

После запуска выдача будет иметь примерно такой вид, то есть, у нас получился хеш с двумя ключами, по каждому из которых лежат списки узлов:
python generate_config.py
servers1: [host1, host2]
srver2: [hosta, hostb]

Немного усложним пример - вынесем блок данных yaml в отдельный файл, config.yaml:
servers1:
  - host1
  - host2
ssrvers2:
  - hosta
  - hostb

Python скрипт же примет вид:
#!/usr/bin/python

import yaml

document = file('config.yaml', 'r')
print yaml.dump(yaml.load(document)

Результат его работы будет аналогичный предыдущему.

Вот так довольно легко и непринужденно можно рисовать конфиг-файлы для своих скриптов :)

Источник: http://pyyaml.org/wiki/PyYAMLDocumentation

четверг, 2 сентября 2010 г.

Вышел Plone 4

Вот новость: http://plone.org/news/plone-4-released, а вот отличный пошаговый курс по новым фичам http://plone.org/products/plone/features

Из волнующих лично меня изменений в первую очередь стоит отметить, что теперь используется Python 2.6 (ссылка), 3я же версия Plone не работала ни с 2.5 ни с 2.6, что вызывало много проблем при установке Plone. Если же говорить о планах на будущее, то 4.1 версия будет поддерживать Python 2.7 (ссылка).

Также не стоит забывать, на базе чего работает Plone - это платформа приложений Zope. Plone 4 базируется на ее 2.12 версии (ссылка). Также обращаю внимание, что не стоит искать эту версию на офсайте Zope 2, она доступна через egg: http://pypi.python.org/pypi/Zope2/2.12.8

четверг, 17 июня 2010 г.

Защита от запуска нескольких инстансов (экземпляров) Perl / Python скриптов

Решение для Perl

Стоит задача - есть некий скрипт, который производит определенные действия с определенной периодичностью. Вызов скрипта в определенном случае может заблокироваться (допустим, ожиданием ввода-вывода). При этом следом может запуститься вторая копия скрипта (интервал не велик), третья и далее. Что в итоге приведет к тому, что система после разблокировки рухнет. Допустим, наш скрипт зовут: /usr/bin/ispmanager_fix_fastcgi и написан он на Перле.

Для начала алгоритм - узнаем имя текущего скрипта (ну не захардкоживать же его в самом деле), грепаем выдачу ps aux (текущие запущенные в системе процессы) на предмет наличия указанного. Если находим, то просто завершаемся - значит предыдущий запуск скрипта еще продолжает работать.

Во-первых, тут нам понадобится спец-переменная $0, которая содержит имя исполняемой программы. В моем случае это будет "/usr/bin/ispmanager_fix_fastcgi". То есть, код будет такой:
ps aux | grep "/usr/bin/ispmanager_fix_fastcgi"
Далее нам надо будет исключить из выдачи ps aux скрипт, из которго сделан запрос проверки. Тут нам поможет встроенная переменная $$, содержащая pid текущего процесса, который в пределах системы, разумеется, уникален. То есть, у нас получается нечто вида:

ps aux | grep "/usr/bin/ispmanager_fix_fastcgi" | grep -v "pid"


Также в выдачу ps aux обязательно попадет сам grep, поэтому его также нужно исключить:

ps aux | grep "/usr/bin/ispmanager_fix_fastcgi" | grep -v "pid" | grep -v grep


Итого получается следующий Perl код:

#!/usr/bin/perl

use strict;
use warnings;

unless ( system("ps aux | grep $0 | grep -v grep | grep -v $$ | grep -v '/bin/sh -c' > /dev/null") ) {
print "Duplicate!\n";
exit 0; # another copy already running
}

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

Исключение /bin/sh -c добавлено для Debian cron, где каждая cron задача запускается как два процесса.


Конечно, решение не подойдет для форкащихся процессов, которые имеют одинаковые имена, не подойдет оно и для скриптов запускающихся друг за другом, но если интервал между запусками велик и от него не зависят жизни людей (тут уже ключевые слова звучат, например, как "flock"), то юзать вполне можно :)

Как вариант "красивого решения", могу предложить модуль: Proc::ProcessTable, который на Debian ставится вот так:
apt-get install -y libproc-processtable-perl

Решение для Python

Логику рассуждений повторять не буду, приведу лишь код.

import os

pid = os.getpid()
Nil, scriptname = os.path.split(sys.argv[0])

result = os.system("ps aux | grep '" + scriptname + "' | grep -v grep | grep -v '" + str(pid) + "' > /dev/null" )

if result == 0:
    print "Another copy of script already running"
    sys.exit(0)

четверг, 13 мая 2010 г.

Разработка веб-приложений на базе Pylons, Python

Этот пост представляет собой объединение ряда моих постов под общей темой в единый материал по Pylons.

1. Почему Python круче Perl в веб-разработке. Статья
2. Почему Pylons/Python круче Rails/Ruby и Catalyst/Perl? Статья
3. Установка Pylons 0.9.7 на Debian 5 Lenny. Статья
4. Использование Pylons в продакшене: paster + Nginx Статья
5. Создание первого контроллера. Статья
6. Работа с шаблонами. Статья
7. Передача переменных из контроллера в шаблон. Статья
8. Обработка GET/POST параметров. Статья
9. Работа с сессиями. Статья
10. Подключение базы данных (PostgreSQL, MySQL). Статья
11. Работа с БД посредством SQLAlchemy. Статья
12. Работа с моделью из внешних скриптов. Статья
13. Подключение ToscaWidgets к Pylons для работы с формами. Статья
14. Валидация форм посредством ToscaWidgets. Статья
15. Аутентификация посредством AuthKit. Статья
16. Авторизация посредством AuthKit. Статья

Есть также идея написать еще посту про пагинацию, кэширование и REST интерфейсы. Если Вам интересно что-то конкретное, то милости прошу в комменты :)

пятница, 16 апреля 2010 г.

re.search vs re.match (search vs match) в Python

In a nutshell, match() only attempts to match a pattern at the beginning of a string where search() will match a pattern anywhere in a string. For example:


То есть re.match требует, чтобы паттерн подходил ко ВСЕЙ строке, а re.search срабатывает, если хотя бы часть подстроки совпала с паттерном.

вторник, 13 апреля 2010 г.

Как узнать о ротации лог файла, который Вы читаете?

Пока из вариантов - следить за его размером при каждой итерации чтения, если уменьшился - значит прошла ротация. Но можно узнать, как это сделали в fail2ban, который писан на Python:

2010-04-11 06:45:49,427 fail2ban.filter : INFO Log rotation detected for /var/log/auth.log
2010-04-11 06:45:49,558 fail2ban.filter : INFO Log rotation detected for /var/log/mail.log
2010-04-11 06:45:49,630 fail2ban.filter : INFO Log rotation detected for /var/log/mail.log
2010-04-11 06:45:52,431 fail2ban.filter : INFO Log rotation detected for /var/log/auth.log
2010-04-11 06:45:52,562 fail2ban.filter : INFO Log rotation detected for /var/log/mail.log
2010-04-11 06:45:52,634 fail2ban.filter : INFO Log rotation detected for /var/log/mail.log

пятница, 26 марта 2010 г.

Stackless Python

Вот нашел такой интересный проект: http://stackless.com/ Суть его в том, чтобы добавить в язык "микропотоки", то есть это как потоки в привычном понимании, но реализованные внутри самого интерпретатора и языка. Их использование на порядки проще, чем обычных потоков, так как все делает сам интерперататор. То есть, мы получаем все преимущества потоков без каких-либо затрат со своей стороны (никаки сложных межпроцессных взаимодействий).

суббота, 20 марта 2010 г.

Получение PTR для IP из Python на Debian 5 Lenny

Ставим:
apt-get install -y python-adns



#!/usr/bin/python

import DNS
import string

DNS.ParseResolvConf()


def get_ptr(ip):
a = string.split(ip, '.')
a.reverse()

name = string.join(a, '.') + '.in-addr.arpa'

x = DNS.DnsRequest(name,qtype='ptr')
x.req()

return x.response.answers[0]['data']

print get_ptr('67.195.37.179')



В результате получаем:

python dns.py
llf320063.crawl.yahoo.net

четверг, 18 марта 2010 г.

Выполнение команд на удаленном сервере по SSH2 из Python /Paramiko

Ставим библиотеку Paramiko:
apt-get install -y python-paramiko



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

import paramiko
import sys

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy( paramiko.AutoAddPolicy() )

try:
ssh_connection = ssh.connect('domain.ru', username='xxxx', password='yyyyy')
except paramiko.AuthenticationException:
print "Auth failed"
ssh.close()
sys.exit(0)

( stdin, stdout, stderr ) = ssh.exec_command('cat /proc/mdstat')

for line in stdout.read().splitlines():
print line


ssh.close()



Вот пример запуска команды:

./ssh_command.py
Personalities : [raid1] [raid10] [raid0] [raid6] [raid5] [raid4]
md0 : active raid1 sdb1[1] sda1[0]
4200896 blocks [2/2] [UU]

md1 : active raid1 sdb2[1] sda2[0]
2104448 blocks [2/2] [UU]

md2 : active raid1 sdb3[1] sda3[0]
1458830400 blocks [2/2] [UU]

unused devices:



по материалам: http://jessenoller.com/2009/02/05/ssh-programming-with-paramiko-completely-different/

среда, 17 марта 2010 г.

Пример Python скрипта защиты от DoS / DDoS атак посредством анализа логов


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

import tailer
import re
import os

ips = {}

for line in tailer.follow(open('/var/log/nginx/access.log')):
m = re.match('^(\d+.\d+.\d+.\d+).*?- 400 0 "-" "-" "-" 0.000--$', line)

if m:
print "Blank DoS request: %s" % line

ip = m.group(1)

print "ban ip: %s" % ip
os.system("ban_ip.sh %s" % ip)

m_bot = re.match("^(\d+.\d+.\d+.\d+).*?GET /someurl/ .*?$", line)

if m_bot:
ip = m_bot.group(1)


if ips.has_key(ip):
ips[ip] = ips[ip] + 1

if ips[ip] > 100:
print "ban ip %s" % ip
os.system("ban_ip.sh %s" % ip)
else:
ips[ip] = 0



print "Bot detected request %s ip: %s" % ( ips[ip], ip )
print line



В данном случае после 100 запросов к someurl бот будет забанен.

Python: обработка строк по мере поступления

Для решения этой задачи есть суперская утилита:
http://code.google.com/p/pytailer/


Ставим Python и easy_install:

apt-get install -y python python-setuptools


На CentOS команды иные:
yum install -y python-setuptools


Ставим tailer:

easy_install tailer


Пишем скрипт:

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

import tailer

for line in tailer.follow(open('/var/log/nginx/access.log')):
print line


Вот и все, можно теперь любым способом обрабатывать приходящие строки.

Оценка производительности 14 серверов приложений на Python

http://www.opennet.ru/opennews/art.shtml?num=25827

Однако, mod_wsgi жуткий обжора :)

вторник, 16 марта 2010 г.

Работа с Zeo из Python

Для начала ставим Zope/Zeo: http://phpsuxx.blogspot.com/2010/03/zope-2123-debian-5-lenny.html


#!/usr/bin/env python

from ZEO.ClientStorage import ClientStorage
from ZODB import DB
import transaction

class MyRemoteZODB(object):
def __init__(self, server, port):
server_and_port = (server, port)
self.storage = ClientStorage(server_and_port)
self.db = DB(self.storage)
self.connection = self.db.open()
self.dbroot = self.connection.root()

def close(self):
self.connection.close()
self.db.close()
self.storage.close()

# write data

mydb = MyRemoteZODB('localhost', 8100)
dbroot = mydb.dbroot

dbroot = mydb.dbroot
dbroot['a_number'] = 3
dbroot['a_string'] = 'Gift'
dbroot['a_list'] = [1, 2, 3, 5, 7, 12]
dbroot['a_dictionary'] = { 1918: 'Red Sox', 1919: 'Reds' }
dbroot['deeply_nested'] = { 1918: [ ('Red Sox', 4), ('Cubs', 2) ],1919: [ ('Reds', 5), ('White Sox', 3) ], }

transaction.commit()
mydb.close()

# read data

mydb = MyRemoteZODB('localhost', 8100)
dbroot = mydb.dbroot

for key in dbroot.keys():
print key + ':', dbroot[key]

mydb.close()



Как результат будет примерно такое:

a_list: [1, 2, 3, 5, 7, 12]
a_dictionary: {1918: 'Red Sox', 1919: 'Reds'}
a_string: Gift
Application:
a_number: 3
deeply_nested: {1918: [('Red Sox', 4), ('Cubs', 2)], 1919: [('Reds', 5), ('White Sox', 3)]}


Ну что, нравится? :)) О сокращении стоимости разработки при использовании вот такой штуки мне даже страшно думать! Даже если располагать базы только на SSD это будет все равно дико экономически эффективно.

Источник примеров: http://www.ibm.com/developerworks/aix/library/au-zodb/

понедельник, 15 марта 2010 г.

Что использовать - Zope 3 или же Zope 2?

http://blogs.nuxeo.com/dev/2005/10/zope2-vs-zope3-faq.html

Частично цитирую:

Should I use Zope 2 or Zope 3?
Short answer:
If you need a product that runs on Zope 2, like for example CPS, Plone or Silva, you should use Zope 2. Otherwise you should use Zope3.


Ну и вкратце для любителей "оно лучше" / "оно хуже" отвечаю - "они разные" (Фактически, это разные ветки без совместимости между друг другом. Разве что названием совпадают), но если нужны все спец фичи - юзайте Zope 3 и не задумывайтесь особо :) Все остальные озвученые продукты сделаны на основе Zope 2 не от того, что Zope 3 плохой, а из-за того, что нет смысла их портировать на "другой" Zope 3.

Хотя с другой стороны, по означенной выше причине (Plone и ко), к 3ей версии скорее всего интерес меньше и как следствие проблемы с документацией и, возможно, со стабильностью работы. Также есть ориентированность тройки не на создание сайтов, а на обычную веб-разработку, что также немного сокращает целевую аудиторию.

Так что лично я для себя решил использовать Zope2.

Будущее наступило! ZODB

Хорошая статья по работе с объектной базой данных ZODB: http://www.komtet.ru/info/zope/vvedenie-v-zodb.-avtor-michel-pelletier а вот мануал по работе с ZODB / Zeo http://www.ibm.com/developerworks/aix/library/au-zodb/

А вот измерение скоростных характеристик: http://209.85.135.132/search?q=cache:opzIpUGB4w4J:zope3.ru/stati/testiruem-zodb-na-skorost+zodb&cd=4&hl=ru&ct=clnk&gl=ru

И вот еще - http://www.upfrontsystems.co.za/Members/roche/where-im-calling-from/zodb-benchmarks-revisited

И еще: http://www.upfrontsystems.co.za/Members/roche/where-im-calling-from/zodb-benchmarks/

Также есть очень меткая цитата про ZODB - "ZODB is a low-write high-read database".

воскресенье, 14 марта 2010 г.

Pylons: подключение ToscaWidgets к Pylons для работы с формами

Есть вот такая обалденная штука: http://toscawidgets.org/ К ней прилагается куча готовых виджетов, их можете найти здесь: http://pypi.python.org/pypi?:action=search&term=tw&submit=search

Ставим сам ToscaWidgets:

easy_install ToscaWidgets


Ставим виджет работы с формами (к слову, есть еще tw.dynforms, но о нем, думаю, позже):

easy_install tw.forms


Далее двигаемся по инструкции по интеграции ToscaWidgets с Pylons: http://toscawidgets.org/documentation/ToscaWidgets/install/pylons_app.html

Открываем настройки middleware:
vi myapp/config/middleware.py


Добавляем в самый верх:
import tw.api as twa


Далее после строки "CUSTOM MIDDLEWARE HERE" добавляем следующее:

app = twa.make_middleware(app, {
'toscawidgets.framework': 'pylons',
'toscawidgets.framework.default_view': 'mako',
})



Теперь открываем контроллер:
vu myapp/controllers/main.py


И в самый верх добавляем подключение виджета:

import tw.forms as twf


И внизу добавляем еще тестовый метод:

def tosca(self):
test_form = twf.TableForm('test_form', action='/main/tosca_save', children=[
twf.HiddenField('id'),
twf.TextField('title'),
twf.TextField('year', size=4),
twf.CalendarDatePicker('release_date'),
twf.SingleSelectField('genera', options=['', 'Action', 'Comedy', 'Other']),
twf.TextArea('description'),
])

return test_form()


И теперь вызываем со сети наш контроллер: http://xx.xx.xx.xx:5000/main/tosca и любуемся довольно миловидными формочками :)

воскресенье, 7 марта 2010 г.

Почему Plone не работает с Python 2.5, 2.6 ?

Пруфлинк: http://plone.org/documentation/manual/developer-manual/managing-projects-with-buildout/prerequisites


А вот обсуждение:
http://regebro.wordpress.com/2010/02/12/yes-python-2-6-is-backwards-compatible/

И планы на будущее:
http://blog.hannosch.eu/2008/12/plone-versus-python-3.html

Установка Plone 3.3.4 на Debian посредством инсталлятора с сайта

Окончательно замучавшись в попытках собрать Zope / Plone руками и по отдельности я сдался и воспользовался инсталлятором с офсайта. Что же, он пашет на ура и ничуть не портит систему :)


cd /usr/src
wget http://launchpad.net/plone/3.3/3.3.4/+download/Plone-3.3.4-UnifiedInstaller.tgz
tar -xf Plone-3.3.4-UnifiedInstaller.tgz
cd Plone-3.3.4-UnifiedInstaller


Ставим зависимости:
apt-get install gcc g++ python-dev zlib1g-dev


Запускаем инсталляцию:

sh install.sh standalone --instance=/opt/zinstance --target=/opt/zope


В конце, надеюсь, успешной сборки будет выдано примерно следующее:

###################### Installation Complete ######################

Plone successfully installed at /opt/zope
See /opt/zinstance/README.txt
for startup instructions

Use the account information below to log into the Zope Management Interface
The account has full 'Manager' privileges.

Username: admin
Password: xxxxxx

This account is created when the object database is initialized. If you
change the password later, you'll need to use the new password.

- If you need help, ask the mailing lists or #plone on irc.freenode.net.
- The live support channel also exists at http://plone.org/chat
- You can read/post to the lists via http://plone.org/forums

- Submit feedback and report errors at http://dev.plone.org/plone
(For install problems, specify component "Installer (Unified)")



В итоге распределение по папкам будет следующее:

ls /opt/zope/
Python-2.4 Zope-2.10.11-final-py2.4 buildout-cache


А сам Plone:

ls /opt/zinstance/
README.txt bin buildout.cfg fake-eggs products var
adminPassword.txt bootstrap.py develop-eggs parts src versions.cfg


Запускаем Plone:

cd /opt/zinstance
bin/plonectl start


Заходим в админку управления Zope http://xx.xx.xx.xx:8080/manage либо прямо в Plone http://xx.xx.xx.xx:8080/Plone

Офсайт Plone: http://plone.org