Django New Relic uWSGI

  • Устанавливаем New Relic
    pip install newrelic
  • Лицензионный ключ берем из личного кабинета, генерируем конфигурацию
    newrelic-admin generate-config LICENSE-KEY newrelic.ini
  • В конфигурации правим название приложения
    # The appplication name. Set this to be the name of your
    # application as you would like it to show up in New Relic UI.
    # The UI will then auto-map instances of your application into a
    # entry on your home dashboard page.
    app_name = app.name
  • Модифицируем project/wsgi.py
    import os
    import newrelic.agent
    newrelic.agent.initialize('/path/to/newrelic.ini')
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
    from django.core.wsgi import get_wsgi_application
    application = get_wsgi_application()
    application = newrelic.agent.wsgi_application()(application)
  • Правим конфигурацию uwsgi.ini
    #module = django.core.handlers.wsgi:WSGIHandler()
    module = project.wsgi
    eval = import newrelic.agent, wsgi; application = newrelic.agent.wsgi_application()(wsgi.application)

sql_joined_field sphinx Django m2m

Необходимо включить результаты поиска по полю name, связанной m2m модели Category.
Модели:

class Category(models.Model):
    name = models.CharField(_(u'Название категории'), max_length=60, unique=True)
    ...
class Product(models.Model):
    ...
    category = models.ManyToManyField(Category, verbose_name=u'Категория', related_name='products')
    ...

Конфиг сфинкса:

sql_attr_multi = uint category from query; SELECT product_id, category_id FROM core_product_category
sql_joined_field = category from query; SELECT core_product_category.product_id, name \
FROM core_category join core_product_category on core_category.id=core_product_category.category_id order by core_product_category.product_id ASC

ascii codec can't encode characters in position "" Django Supervisor

В конфиг supervisor добавляем

environment=LANG="ru_RU.utf8", LC_ALL="ru_RU.UTF-8", LC_LANG="ru_RU.UTF-8"

При обновлении MySQL миниатюры изображений, отрисованные с помощью Pillow и easy_thumbnails для Django, могут перестать работать, рецепт такой же, добавить локаль в конфиг supervisor и перезапустить его.

Django Ajax

Нашел чудесную библиотеку django-ajax, берет на себя всю рутину, связанную с ajax во вьюшках Django.
Вьюшка теперь может выглядеть так:

from django_ajax.decorators import ajax
from models import Product
from cart.cart import Cart
@ajax
def ajax_add_to_cart(request):
    if 'product_id' in request.GET and request.GET['product_id']:
        product_id = request.GET['product_id']
        product = Product.objects.get(id=product_id)
        cart = Cart(request)
        cart.add(product, product.price, quantity=1)
        items_in_cart = cart.itemCount()
        return {'items_in_cart': items_in_cart}

Ответом будет JSON такого вида

{"status": 200, "statusText": "OK", "content": {"items_in_cart": 5}}

Шаблон может выглядеть так:

<a class="in-cart" href="{% url 'add_to_cart' item.id 1 %}">в корзину</a>
<script type="text/javascript">
    $(function() {
                var lnk = $("a.in-cart");
                $(lnk).click(function() {
                    $.get($(lnk).attr('href')).done(function( json ) {
                        $("#items_in_cart").text(json.content.items_in_cart)
                    });
                    return false
                });
            });
</script>

BG, FG, %, &, JOBS, CTRL+Z, DISOWN

Запуск процесса в фоновом режиме
Амперсанд & после команды запустит ее в фоновом режиме.

cp -pR /home/ /mnt/bacup/ &

С работающей командой тоже самое можно сделать так: нажать CTRL+Z

:~$ cp -pR /home/ /mnt/backup/
^Z
[1]+  Stopped                 cp -pR /home/ /mnt/backup/
:~$ ps ax | grep cp | grep -v grep
4833  2.9  0.0  14184   872 pts/0    T    11:40   0:01 cp -pR /home/ /mnt/backup/

Как видим процесс находится в STAT T
Набираем bg для того, чтобы запустить команду в фоне

:~$ bg
[1]+ cp -pR /home/ /mnt/backup/ &
:~$ ps ax | grep cp | grep -v grep
 4833 pts/0    R      0:01 cp -pR /home/ /mnt/backup/
:~$

Процесс перешел в STAT R и выполняется в фоне, фоновый процесс называется job (задание)
Посмотреть список заданий можно командой jobs

:~$ jobs
[1]   Stopped                 cp -pR /home/ /mnt/sdb/
[2]   Stopped                 vim 1.txt
[3]-  Stopped                 vim 2.txt
[4]+  Stopped                 vim 3.txt
  • + — текущая задача.
  • — последняя задача
  • К остальным задачам можно обратиться по их идентификационному номеру.

Запустить задачу в foreground

  • Команда fg без параметров или fg + запустит текущую задачу (со знаком +) в foreground
  • fg +
  • Команда fg — запустит последнюю задачу (задача со знаком )
  • fg -
  • Запустить задачу можно по их идентификационному номеру
    fg 2
    fg %2
  • Вместо fg можно использовать просто знак процента %
    %+
    %-
    %2

Команда disown используется для отделения задачи от таблицы задач текущего shell. При отделении задачи от текущего shell, ее родителем становится INIT. После это можно завершить текущий shell, команда продолжит выполняться. На самом деле, если отправить команду в background, а потом завершить сессию, произойдет тоже самое, т.е. родителем станет INIT

:~$ disown %2
:~$ ps -fe | grep cp | grep -v grep
s0x90      5346     1  6 12:56 ?        00:15:24 cp -pR /home/ /mnt/backup/
:~$ yes > /dev/null &
[1] 6576
:~$ ps -f | grep yes | grep -v grep
s0x90      6576  6144 96 17:26 pts/0    00:00:10 yes
:~$ logout
:~$ ps -fe | grep yes | grep -v grep
s0x90      6576     1 91 17:26 ?        00:01:15 yes

Не забывайте про чудесную утилиту-мультиплексор screen

logrotate зависает в STAT D

По неизвестной причине logrotate перестал удалять старые архивы журналов, в результате образовалась директория размером в 160M и logrotate просто зависал в STAT D (ожидание системы ввода/вывода), отъедая весь процессор и большую часть оперативной памяти.
Удалил директорию через rm -r, удалялось часа 4.
logrotate продолжал виснуть, но теперь уже в STAT R, спотыкаясь на ротации btmp. Помогла очистка/var/lib/logrotate/status

rm /var/lib/logrotate/status && touch /var/lib/logrotate/status

Причина такого поведения, к сожалению, так и неизвестна, конфиги в /etc/logrotate.d/ верные.

Sysstat мониторинг производительности системы

sysstat — удобная утилита для измерения и анализа производительности системы. Можно получить доступ к системным характеристикам (загруженность процессора, i/o wait, использование памяти и прочее) указав в качестве параметра временной интервал, например статистику за последний день можно получить так.

sar -u
Linux 2.6.32-5-686 (debian.server)    21.11.2013      _i686_  (1 CPU)
13:05:01        CPU     %user     %nice   %system   %iowait    %steal     %idle
13:15:01        all      1,55      0,00      0,46      0,62      0,00     97,36
13:25:01        all      1,30      0,00      0,45      0,45      0,00     97,80
13:35:01        all      2,98      0,00      0,58      0,69      0,00     95,75
13:45:01        all      1,78      0,00      0,50      0,65      0,00     97,07
13:55:01        all      1,23      0,00      0,46      0,53      0,00     97,78
14:05:01        all      3,24      0,00      3,36      1,59      0,00     91,81
14:15:01        all      1,83      0,00      0,51      0,74      0,00     96,92
Среднее:        all      1,99      0,00      0,90      0,75      0,00     96,36

Читать далее Sysstat мониторинг производительности системы

django-simple-history трекинг истории изменения объекта

В джанго есть встроенный трекер истории, но он не позволяет откатиться на предыдущее состояние. Решить эту задачу можно с помощью удобного инструмента django-simple-history.

pip install django-simple-history

В settings.py

INSTALLED_APPS = (...
    'simple_history',
...)

В models.py

from simple_history.models import HistoricalRecords
class Product(models.Model):
    ...
    history = HistoricalRecords()

Выполняем миграцию

./manage.py schemamigration <app_name> --auto
./manage.py migrate <app_name>

Далее в admin.py

from simple_history.admin import SimpleHistoryAdmin
class ProductAdmin(SimpleHistoryAdmin, admin.ModelAdmin):
    ...
admin.site.register(Product, ProductAdmin)

Теперь при нажатии на кнопку «История» объекта можно откатиться на выбранную ревизию.

Автостарт pptp туннеля Debian

В

/etc/init.d/

добавляем скрипт

#! /bin/sh
### BEGIN INIT INFO
# Provides:          pptp tunnel
# Required-Start:
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      1 0 6
# Short-Description: start pptp session
### END INIT INFO
case "$1" in
    start)
        pon <peer_name> &
        echo "PPTP Started"
        ;;
    stop)
        poff <peer_name_
        ip ro del <some_route_del>
        ip ro del <some_route_del>
        echo "PPTP Stopped"
        ;;
    *)
        echo "Usage: /etc/init.d/pptp-<peer_name> {start|stop}"
        exit 1
        ;;
esac
exit 0
insserv -v /etc/init.d/pptp-<peer_name>