- Устанавливаем 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>
Rsync via ssh
Настраиваем ssh по ключу
Добавляем в крон
rsync --delete -crpz -e "ssh -i /path/to/private_key -p <ssh_port>" user@example.com:/path/to/dir/ /path/to/dir
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 2 fg %2
%+ %- %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
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>