2016年4月24日日曜日

Lavie Light に Xubuntu16.04 をインストール

LTS(Long Term Support)が出たので、早速インストール。

1.ISO入手

http://xubuntu.org/getxubuntu/
⇒ 32-bit systems

2.USBに焼く

USBメモリに、インストール用ISOを焼く
# sudo dd if=xubuntu-16.04-desktop-i386.iso of=/dev/sdb bs=512k

3.USBから起動

そのままだとエラーで止まるので、起動オプションを設定
参考: https://wiki.ubuntulinux.jp/UbuntuTips/Others/BootOptions

⇒ acpi=off を選択

# このようなエラーが出ました。
# irq 9: nobody cared (try booting with the "irqpoll" option)
# Disabling IRQ #9

4.イントール

普通にインストール

5.その他、アプリケーションのインストール

いつものように、シェルスクリプトで。

FILE: setup.sh
--
#!/bin/sh

### http://askubuntu.com/questions/14629/how-do-i-enable-the-partner-repository
sed -i "/^# deb .*partner/ s/^# //" /etc/apt/sources.list

### http://www.webupd8.org/2012/01/install-oracle-java-jdk-7-in-ubuntu-via.html
add-apt-repository ppa:webupd8team/java

apt-get update
apt-get upgrade

apt-get -y install dnsmasq mosh sshfs python-dev python-pip gparted fcitx-mozc geany eclipse x2goclient ubuntu-restricted-extras lame asunder audacity handbrake totem chromium-browser chromium-browser-l10n adobe-flashplugin privoxy oracle-java7-installer mtp-tools mtpfs

pip install virtualenv

### Pillow Image Lib ###
apt-get -y build-dep python-imaging
apt-get -y install libjpeg8 libjpeg62-dev libfreetype6 libfreetype6-dev

### mecab ###
apt-get -y install mecab libmecab-dev mecab-ipadic mecab-ipadic-utf8 python-mecab

reboot
--

6.所感

普通に、使いやすいです。満足。

2016年4月17日日曜日

Xubuntu14.04 に、Chromium + Flash をインストール

しばらく前からChromeを起動すると「このLinuxシステムはサポートが終了するため、このパソコンでは間もなくGoogle Chromeのアップデートが受信されなくなります。」と表示されるようになった。
知りべてみると、Xubuntu(32bit)では、Chrome を使わない方が良さそう。

どうやら、Chromium で代替できるようなので、早速、インストールした。

# apt-get update
# apt-get install chromium-browser chromium-browser-l10n

でも、ウェザーニュースが見れない..
Chromium は、別途 Flash のインストールが必要とか。

更に調べて、みごと解決。

メニュー → 設定 → ソフトウェアとアップデート
「他のソフトウェア」のタブを開く
「Canonicalパートナー」にチェックを入れる

Flash をインストール。

# apt-get update
# apt-get install adobe-flashplugin

Chromium を開いて、確認
→ chrome://plugins/

無事に、Chromium + Flash を使えるようになりました。

2016年3月21日月曜日

Celery を Supervisor で、デーモン化

こちらの続きです。
http://yamayoshi.blogspot.jp/2016/02/django18-celery3120-db.html

将来的に、1台のサーバーで複数のアプリを使いたいので、Supervisor を選択。

1.Supervisor インストール

$ sudo apt-get install supervisor

2.設定

File: /etc/supervisor/conf.d/celery.conf
--
[program:celery]
command=celery worker -A mysite -l info
directory=/path/to/env/proj ⇒ Django プロジェクトの場所を指定
environment=PYTHONPATH=/path/to/env/lib/python2.7/site-packages
 ⇒ Django パッケージの場所を指定
user=www-data ⇒ 起動ユーザを指定
numprocs=1
stdout_logfile=/var/log/celery/worker.log
stderr_logfile=/var/log/celery/worker.log
autostart=true
autorestart=true
startsecs=10
stopwaitsecs = 600
killasgroup=true
priority=1000
--

元は、こちら。
https://github.com/celery/celery/blob/3.1/extra/supervisord/celeryd.conf

3. 起動とステータスの確認

$ sudo /etc/init.d/supervisor start
$ sudo supervisorctl status

4.まとめ

PYTHONPATH で少し悩んだけど、また1つ勉強になりました。

2016年2月14日日曜日

Django1.8 と Celery3.1.20 で、DBに非同期書き込み

やりたいことはタイトルの通りだけど、Webの情報に翻弄され、中々ゴールに辿りつけず。
忘れない内に、メモメモ。

環境
Ubuntu14
RabbitMQ
Django1.8
Celery3.1.20

1.RabbitMQ インストール

$ sudo apt-get install rabbitmq-server

2.Django インストール

$ cd
$ virtualenv env
$ source ~/env/bin/activate
$ pip install --upgrade pip
$ pip install Django==1.8 celery==3.1.20
$ pip freeze
$ cd env

3.アプリケーション

$ django-admin.py startproject proj
$ cd proj
$ python manage.py startapp app1

〜 中略 〜 ※本論では無いので、一旦省略(^^;

4.Django で Celery を使えるようにする。

マニュアルは、こちら
http://docs.celeryproject.org/en/latest/django/index.html

4-1.ファイル構成

proj/
├manage.py
├proj/
│├__init__.py  # 4.3参照
│├settings.py
│├celery.py    # 4.2参照
│└urls.py
└app1/
 ├admin.py
 ├models.py
 ├views.py     # 6参照
 └tasks.py     # 5参照

4-2.Celery インスタンスを定義

File: proj/proj/celery.py
--
from __future__ import absolute_import
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'proj.settings')
from django.conf import settings
app = Celery('proj')
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
--

4-3.Django 起動時にインスタンスをロード

File: proj/proj/__init__.py
--
from __future__ import absolute_import
from .celery import app as celery_app
--

5.非同期にDBに書き込むタスクを定義

File: proj/app1/tasks.py
--
from __future__ import absolute_import
from celery import shared_task
from .models import Word

@shared_task
def put_word(word):
 w, c = Word.objects.get_or_create(word=word)
 return "ok"
--

# models.py の説明は省略してます。

6.Vewからタスクに渡す

File: proj/app1/views.py
--
from .tasks import put_word

def test(request):
 word = "xxxxxxxx"
 put_word(word)
 return HttpResponse("ok")
--

# urls.py の説明は省略しています。

7.開発サーバを起動して、動作確認

$ celery -A proj worker -l info
$ python manage.py runserver

8.まとめ

Google App Engine では標準で使える機能を、自前で実装できました。
データベースへの書き込みは、レスポンスへの影響が大きい為、できる限り非同期で実行させたいもの。
日本語の情報も少なく、少し苦労したので、どなたかの参考になれば、幸いです。

2016年1月21日木曜日

Ubuntu14.04で、NginxとuWSGI(emperor)を構築

ABLE.net の VPS で、WEBサーバを構築する手順です。

1. インストール

$ sudo apt-get install nginx uwsgi uwsgi-plugin-python python-pip

2. ポートを開く

$ sudo ufw allow 80

3. Nginx の設定

デフォルトのサイト設定を削除しておきます。

$ sudo rm /etc/nginx/sites-enabled/default

設定ファイルの例です。

FILE: /etc/nginx/conf.d/<サイト名>.conf
--
server {
 listen 80;
 server_name <サイトURL>;
 location / {
  uwsgi_pass unix:/tmp/<サイト名>.sock;
  include uwsgi_params;
 }
}
--
※ UNIXソケット(.sock)で、uWSGI に連結します。

再起動しておきます。
$ sudo service nginx restart

4. uWSGI (emperor) の設定

必要なディレクトリを作成します。

$ sudo mkdir -p /etc/uwsgi/vassals
$ sudo mkdir -p /var/log/uwsgi

設定ファイルです。

FILE: /etc/init/uwsgi.conf
--
description "uWSGI"
start on runlevel [2345]
stop on runlevel [06]
respawn
env UWSGI=/usr/local/bin/uwsgi
env LOGTO=/var/log/uwsgi/emperor.log
exec $UWSGI --master --emperor /etc/uwsgi/vassals --die-on-term --logto $LOGTO
--

emperorモードで起動し、/etc/uwsgi/vassals の iniファイルを監視します。

$ sudo service uwsgi restart

5. Django の動作確認

virtualenv 環境に、Django を入れます。

$ cd
$ virtualenv venv
$ cd venv
$ source bin/activate
$ pip install Django
$ django-admin.py startproject mysite
$ cd mysite

$ deactivate

6. uWSGI 設定ファイル

Nginx から uWSGI に連結する為に、iniファイルを作成します。

設定ファイルの例です。

FILE: /etc/uwsgi/vassals/<サイト名>.ini
--
[uwsgi]
# Variables
base = /home/<ユーザ名>/venv
app  = <サイト名> # Djangoのデフォルトは、mysite
# Generic Config
home   = %(base)
chdir  = %(base)/%(app)
module = mysite.wsgi
socket = /tmp/%n.sock
chmod-socket = 666
py-autoreload = 1 #reload on change python file
plugins = python
--

7.まとめ

全体の繋がりは、以下の通り。

 WEBアクセス -> Nginx -> uWSGI -> Django

複数のサイトを動かす場合は、
・Nginx の <サイト名>.conf
・uWSGI の <サイト名>.ini
・アプリケーション(Django等)
を準備します。

Ubuntu14.04 + Nginx で、画像のリサイズを行う。

こちらの続きです。
http://yamayoshi.blogspot.jp/2013/05/ubuntu1204-nginx.html

やりたいこと。
・任意のサイズを指定
・任意のアドレスを指定

元の画像: http://<アドレス>/<パス>/<ファイル>
 ↓
リサイズ: http://<変換サーバのアドレス>/g<サイズ>/<アドレス>/<パス>/<ファイル>

1.インストール

$ sudo apt-get install nginx

2.設定

FILE: /etc/nginx/conf.d/<app>.conf
--
server {
 listen 80;
 server_name www.example.com;
 resolver localhost;

 location / {
  uwsgi_pass unix:/tmp/<app>.sock;
  include uwsgi_params;
 }

 location ~ ^/g(?P<size>[^/]+)/(?P<url>[^/]+)/(?P<file>.*)$ {
  rewrite ^ /crop last;
 }

 location /crop {
  image_filter crop $size $size;
  proxy_pass http://$url/$file;
  add_header Nginx "$size $url $file";
 }
}
--

ちょこっと説明

> location ~ ^/g(?P<size>[^/]+)/(?P<url>[^/]+)/(?P<file>.*)$
 → サイズ、アドレス、ファイル(パスを含む) の情報を取り出して、変数に格納します。

> image_filter crop $size $size;
 → 変換サイズを指定

> proxy_pass http://$url/$file;
 → 元の画像ファイルを指定

> add_header Nginx "$size $url $file";
 → おまけ(HTTP_HEADERに変数を出力し、Chrome開発ツールで確認。)

3.起動/停止

$ sudo service nginx stop … 停止
$ sudo service nginx start … 起動

4.動作確認

ブラウザから、

http://www.example.com/g160/3.bp.blogspot.com/-qn0m7KScp4A/TsTyX4cO5FI/AAAAAAAAANA/ooqc_7cGnis/s1600/NEC_0025.JPG

にアクセスすると、

http://3.bp.blogspot.com/-qn0m7KScp4A/TsTyX4cO5FI/AAAAAAAAANA/ooqc_7cGnis/s1600/NEC_0025.JPG

のサムネイル画像を表示します。

キャッシュを使う場合は、前回の記事を参考に。

2015年7月17日金曜日

GAE/P NDB のクエリで、2つの不等式を使う。

Google App Engine は、クエリの中で複数のプロパティに対して不等式を使うことが出来ません。
これ、結構不便です..

例えば、開始日と終了日の2つのプロパティに対して、
 開始日 < 7月10日 and 終了日 > 7月20日
と云うようなクエリは実行できないのです..

で、イロイロと調べて、こんな記事を見つけました。
http://stackoverflow.com/questions/22176586/optimizing-a-inequality-query-in-ndb-over-two-properties

クエリで1つ目の不等式を使い、iterで2つ目の不等式を使うのか。なるほど!!

続いて、こんな記事も見つけた。
http://ae-book.appspot.com/static/pgae-ndb-20121009.pdf

なるほど、iter で cursorも使えそうだな。

と、ここまでは良かったけど、どうも projection と cursor は一緒に使えないみたい..残念。

で、結論は、こんな感じに。

[モデル]
class Event(ndb.Expando):
 start_dt = ndb.DateProperty()  #開始日時
 end_dt = ndb.DateProperty()   #終了日時

[スクリプト]
next_curs = request.GET['curs']
cnt = 10
it = Event.query(Event.end_dt >= dt1).iter(projection=[Event.start_dt])
keys = []
if next_curs is not None:
 next_curs = int(next_curs)
 for e in it:
  if e.key.id() == next_curs:
   keys.append(e.key)
   break
next_curs = None
for e in it:
 if e.start_dt <= dt2:
  keys.append(e.key)
  if len(keys) >= cnt+1:
   next_curs = keys[cnt].id()
   keys.pop()
   break

主なポイントは、以下の通り。
 Event.query(Event.end_dt >= dt1) → 1つ目の不等式
 if e.key.id() == next_curs: → カーソル位置(キーID)まで早送り
 if e.start_dt <= dt2: → 2つ目の不等式
 if len(keys) >= cnt+1: → cnt件までループ