旧サーバー停止

今年3月より行なってきたサーバー引越も先月終了。リファレンス用に稼働していた旧サーバー(marocha.marochanet.org)を今月末の契約終了を受けて本日停止しました。これをもって来月より新サーバー(jagha.marochanet.org)単独での運用になります。2013年7月から稼働してきた「さくらVPS(V3)2Gコース」。CentOS6にて運用開始し、2020年初頭にCentOS8にアップグレード。安定してきたところでCentOSサポート終了予定のお知らせ。それを受けてのサーバー引越でした。

さくら「VPS(V5)2GのSSD100Gコース」に無料でSSD100G追加キャンペーンに釣られての流れになるけど、Ubuntuサーバーへの引越と同時に出来て丁度良い感じでした。

まぁ、WEBサイト的には、見た目は何も変らないので変化を感じることは無いけど。。。

新サーバー(jagha):marocha君、8年間お疲れさまでした。
ちなみにmarochaはFinalFnatasyXIをプレイしていたときのメインキャラクター名(ホントはSemicolonというキャラがメインだったのだが、タルタル族の可愛さに徐々のサブキャラのmarochaで活動する機会が増え、最後にはサブがメインになってしまったというオチ)で、jaghaは現在プレイしているFinalFantasyXIVのメインキャラ名です。こちらにもmarochaというサブキャラが居るけど、今のところメインを乗っ取る気配は無さそうだ。。。

djangoセキュリティログ追加

チュートリアルを使用したdjangoの勉強と並行して、djangoで構成している本サイトのポータルページもある程度のセキュリティー対策が急がれる。djangoを素で使用しているサイトは少ないようでwordpressのようにBOTによる攻撃はまだ見られない。何らかのCMSを使用しているのを見越して適当なURLをぶっ込んでくるBOTは404で弾けるのであまり問題にならないが、ごくたまーに、しつこくadminでログインしようとする輩が現れるようだ。

このWordpressのサイトでも結構多かったので(普通に見に来てくれる人は殆ど居ないのにwww)、User Login Historyというプラグインを入れている。ここもたまに100回以上のadminログイン試行をしてくる輩がいるので、このログを利用してIPを特定しblockset.pyで手動だけどお引き取り願うことにしている。

同じような仕組みをdjangoのポータルページにも仕掛けようと勉強がてら色々と調べたところ、ログイン用の認証バックエンドという仕組みが利用できそうだということが分かった。デフォルトの<project>/setting.pyには明示的に定義はされていないが(django.conf.global_settings にデフォルト定義)、AUTHENTICATION_BACKENDSという配列がありここのカスタムや追加の認証バックエンドを追加出来る(<project>/settings にて再定義)

デフォルトでは’django.contorib.auth.backends.ModelBackend’が一つ定義されているので、こちらを継承カスタマイズして認証結果をログ出力できるようにする方針とする。

django.contrib.auth.backends.ModelBackend 抜粋
class ModelBackend(BaseBackend):
    """
    Authenticates against settings.AUTH_USER_MODEL.
    """

    def authenticate(self, request, username=None, password=None, **kwargs):
        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        if username is None or password is None:
            return
        try:
            user = UserModel._default_manager.get_by_natural_key(username)
        except UserModel.DoesNotExist:
            # Run the default password hasher once to reduce the timing
            # difference between an existing and a nonexistent user (#20760).
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user
       ・・・・・・

認証判定にはメソッドauthenticateが機能しており、認証OKであればusernameを、NGであればNoneを返す関数であるため、クラス継承により下記のようにメソッドをオーバーライドして再定義する

<project>/backends.py
from django.contrib.auth.backends import ModelBackend
from logging import getLogger # using logging module

class ModelLogBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        logger = getLogger('loginInfo') # example
        res = super().authenticate(request, username, password, **kwargs)
        if res is None:
            logger.info('login faild, bad user: %s' % username)
        else:
            logger.info('user logged in : %s' % username)
        return res

super()で親クラスのメゾッドに丸投げして、結果に応じてログを吐き出す機構を追加。継承したクラスを新たなバックエンドとして<project>/settings.pyに定義する。

# Authntication backend
AUTHENTICATION_BACKENDS = [
    '<project>.backends.ModelLogBackend'
]

<project>はdjangoのプロジェクト名に置き換える。

ちなみにloggerの設定は別の記事を参照して完成しておくこと。当サイトの場合は他のアクセスログの都合でstructlogを使用している(設定さえしておけばloggingと同等に使用可能)。

もともと、ポータルとしてのdjangoサイトは出来上がっていたので、この機能を付けたくてdjangoの本格勉強を始めたという流れでした。蓋を開けてみると思ったより簡単で、同時にカスタマイズ性の高さに今更ながら感動です。次はdjabngo+bootstrap(japascript)による動的サイトの実装実験を目指したいな。

金魚飼育

何年か前の記事にメダカの飼育をはじめたというネタがあったが、まずはそれの顛末から。

第一世代は卵を産んでくれたあとすぐに全滅してしまったが、これは寿命と環境の影響かなと2世代目に期待をかけたのだが、成魚のなったのは十数匹で3世代目を残してまた全滅。3世代目はどうも元気がなく成魚になる前に全滅してしまった。夏の暑さもあったと思うが、ろ過環境であるとかが大げさなのと、水流の影響でメダカの体力が削られてしまったのではないかと推測。

再び稚魚をいただいてきて、今度はろ過のない昆虫用のプラ水槽で、今に至るわけだが、世代を重ねることはなかなかうまくいかないが、元気に泳いでいるのだった。

メダカの水槽の今

ろ過装置付きの水槽が余ったので、昨年から金魚を飼うことにした。せっかくなのでノッタリクッタリ泳ぐのが可愛い琉金一択でホームセンターのペットショップで3匹購入し、飼育開始。そのうち一匹は胸鰭が奇形であまりうまく泳げないようですぐに死んでしまった・・・(購入時によく確認しなかったのがいけなかった)

昔熱帯魚を飼っていたことがあるので、それよりは簡単だろうとなめてかかっていたら、結構繊細な生き物で、冬のある日水替えをしようと、水槽掃除がてらベランダで一晩カルキ抜きをした水に半分ほど替えたことろ、2匹とも水面に浮いてしまい、水底に潜れなくなってしまった。

転覆病というものらしく、すぐに死ぬわけではないが、原因がいろいろあるため治療も困難。予想では急激な水温変化によって内臓疾患を起こしてしまったのではないかと考える。そのような理由であまり長生きが出来なくてかわいそうだった。

そのような理由でしばらく飼うのは控えていたが、先日またホームセンターのペットショップに安い琉金もどき(ミックス金魚売り場)をお迎えして。以前の反省を踏まえて慎重に水替えしながらの飼育を始めた。

しかし数日経って、また転覆病患者が発生(3匹中1匹)。水温は大丈夫なはずだけど、、、。この個体は買ってきたときから非常に元気で餌を与えると大暴れして水面の空気と一緒に餌をパクパク食べまくっていた(俗にいう空気食い)。まさかそれだけで転覆病になるとは思えないけど、餌のやりすぎという面も考えられるので、早期発見ということでしばらく餌を控えたり、ネットの情報を色々な転覆病の治療方法を探してみた。

やはり大方の原因は内臓疾患のようで、消化不良によりお腹の中にガスがたまるためとのこと。よくよく見るとうちの個体も、糞の中に気泡があったり、まさにそういう原因なんだろうなぁという現象だ。

今回の場合は常に転覆しているわけではなく、朝に餌を与えてから暫く転覆症状がおこり、夕方か夜には回復しているためそれほど深刻ではないので、今のうちに試せることをしてみようと、一番簡単そうな対応から始めることとした。

水槽に水草入れて食べさせるのがよいというお話で、以前からお腹の調子をよくするために植物性の餌が良いなどとして、与えてみたがあまり効果がなかったが、水草を食べるように習慣づければ、毎日の餌にガッツくことは少なくなり、転覆現象も改善されるのではと、試してくることとした。

金魚の水草といえばやっぱりカボンバが人気そうなので、さっそく投入。最初は隠れ場くらいにしか使ってないようだったが、しばらくしてみると、新芽がかじり取られていたり、若い葉っぱが減っていたり、最近では一本抜けて浮いているなど、明らかに食べているだろうという状況。

それが確認できるようになったあたりから、転覆症状の時間が短くなってきた。以前は夕方くらいまでお腹を上にして浮いていたのだが、昼過ぎくらいには普通に泳いでいるのが確認できるようになった。

まぁ、転覆病の治療に「水温を上げる」というのがあるので、これから夏場に向けて水温が上がった結果かもしれないが、引き続き様子を見てみたいを思う。

一番右が転覆病患者。口の下が白い琉金タイプなので、「白くちびる」と呼んでいる。

誰も見ていないような独り言ブログなのでとは言わないが、公の場で「生き物を死なせた」ような話をするのは荒れる原因になるかもしれないが、生き物を飼うということはそういうことに向き合っていくことじゃないかなと思います。決して遊び半分ではないし、いつも癒してもらっている分精一杯お世話したいという気持ちになります。

天の川ホタル祭り

昨年に引続き今年もコロナ禍のため中止で残念なので、2018年に行ったときの写真。

どこかの用水路
ゴミ捨て禁止
右手に星空

場所は滋賀県米原市で毎年開催されている感じ。かつてバスツアーで案内されて依頼お気に入りの場所で雨上がりの週末を狙って見に行くことにしている。

実際のホタル祭り会場はもう少し南だが、写真を撮ったのは左の場所。西にグリーンパーク山東というキャンプ場があるので、そこの駐車場に車を停めて、徒歩で目的の場所へ。

天満神社の森の周辺の水田と水路あたりとなる。南の方は民家が多くなるので神社北東あたりが良いかもしれない。

写真はデジカメのオリンパスPEN(EPL-7)で1~3分程度の露光なので、ホタルが凄くたくさん飛んでいるように見えるが、実際は点滅しながら飛んでいるため、点滅の数だけ光点がが増えているという感じ。

撮影方法としては、夜といえどもそんなに暗いところではないため、3分も露光するとホタルよりも周りが明るくなってしまうので、比較明合成という手法を用いている。

数秒露光で数分連続撮影を行い、明るい部分のみの合成を行う。そのため背景は数秒露光分の撮影のまま、光って移動しているホタルだけが明るく写るという仕組みで、星空の公転軌跡の写真などで使われる方法。

通常は連写データをパソコン・フォトショップなどの編集作業による作成するが、オリンパスPENにはそれをカメラ単体で行う機能がある(ライブコンポジット)(右写真)ので上のような写真が比較的簡単に取ることができる。

実はさらに数年前2014年のスーパー雷雨記事の時の写真もこのライブコンポジットの機能をつかってました。さすがに一発撮りであんなにドンピシャな雷写真は撮れないですね。
ライブコンポジット機能で撮影開始して数分待ち、稲妻が走ったら連写ストップ、という撮り方でした。もちろん画角のどこに稲妻が写るのかは運次第。不発もありましたw

djangoチュートリアルメモ

基本的にはdjangoサイトのチュートリアルをそのままトレース。やった事だけをメモしていこうかと。。。

  • 仮想環境への移行 source bin/activate
  • djangoインストール : pip install Django
  • バージョン確認:python -m django –version → 3.2.4
  • プロジェクト作成:django-admin startproject mysite
  • とりあえずテストサーバー起動:python manage.py runserver 0:8000
    外部からアクセスするため(ただしファイヤーウォールで接続制限をかけること)
  • 「Invalid HTTP_HOST header」エラーが出るので、setting.pyを修正
    ALLOWED_HOSTS = [‘*’]
    デフォルトでは空になっているので、自サイト以外からはアクセスできないようだ
  • チュートリアルに沿ってアプリケーション作成
    python manage.py startapp polls
  • ここまで作った状態で、プロジェクト下とライブラリのdjango下をそれぞれgitの管理化に入れて、pythonの勉強を兼ねて、動作の仕組みを解析する予定。

Git小技

gitignore

djangoプロジェクトをcommitするときに、コンパイル済みの*.pycなどあとから「このファイルは対象外にしたいなー」てなったとき。

  • .gitignoreに無視したいファイルを追加
  • すでにコミットしているファイルを対象外(リポジトリから削除)とする
.gitignore:
*.pyc

git管理のトップディレクトリに移動して、git rmで対象削除する

find . -name "*.pyc" -exec git rm -f "{}" \;

Tree表示

git log をきれいにみる方法

ここのサイトを参考に

git log --graph --pretty=format:'%x09%C(auto) %h %Cgreen %ar %Creset%x09by"%C(cyan ul)%an%Creset" %x09%C(auto)%s %d'

下記コマンドにてエイリアス登録

git config --global alias.tree 'log --graph --pretty=format:"%x09%C(auto) %h %Cgreen %ar %Creset%x09by"%C(cyan ul)%an%Creset" %x09%C(auto)%s %d"'

各ユーザーごとホームディレクトリの.gitconfigに追加される。

あとエディタも使い慣れたのにしたいので、

$ git config --global core.editor emacs

loggerの件(pythonモジュール)

プログラムのデバッグや各種情報を出力するのにprintを使用したり、エラー出力のためにsys.stderr.writeを使った板が、今後djangoなどWEBアプリ開発を念頭に入れて、loggingモジュールを使用できるよう勉強していきたい。

ここのページを参考にすると、なるほどいつもはモジュールをまんまimportしているが、それだとインスタンスを生成せずに使用してしまう可能性もある。なるべく使用するのみをimportするような習慣をつけておいたほうがよさそう。

×import logging
×logger = logging.getLogger(__name__)

〇from logging import getLogger, StreamHandler, DEBUG, INFO
〇logger = getLogger(?__name__)

あとはおまじないの様に、下記コードを追加して出力先とレベルを設定するとよいそうだ

logger = getLogger(__name__)
handler = StreamHandler()
handler.setLevel(DEBEG)
logger.setLevel(DEBUG)
logger.addHandler(handler)
logger.propagate = False

#
#
logger.info('inform')
logger.error('error occerd')

setLevelは2か所あるので、引数をDEBUGなどを変数に格納して、一括で変えられるようにしてもいいかもしれない。

勉強がてら、上記修正をblockset.pyに適用して、sys.stderr.write()の部分をlogger.info()に変更。動作自体は特に変化はないが、ちゃんと作ってる感じが良いかも・・・
日に日に、情報コピペの覚書投稿になりつつある・・・・

python環境整備

ubuntuのインストール直後はpythonコマンドはpython2.7系、3.8系のpythonを使いたければpython3と打たなければならなかった。まぁ仮想環境を構築すれば良いんだけど、サーバー設定環境等全ユーザーで3系を使いたいので、対策した時の覚書き

ググったサイトを参考に、update-alternativesコマンドを使用してデフォルトの起動バージョンを3系とした。

root@server:~# update-alternatives --config python
There are 2 choices for the alternative python (providing /usr/bin/python).

  Selection    Path                Priority   Status
------------------------------------------------------------
  0            /usr/bin/python3.8   2         auto mode
  1            /usr/bin/python2.7   1         manual mode
* 2            /usr/bin/python3.8   2         manual mode

Press <enter> to keep the current choice[*], or type selection number:

こんな感じでpython3が選択されている

ここで、勉強は各種実験用に個人ディレクトリにpython仮想環境を構築(venvを使用)

xxxx@server:~$ python -m venv venv
xxxx@server:~$ cd venv/
xxxx@server:~/venv$ ls
bin  include  lib  lib64  pyvenv.cfg  share
xxxx@server:~/venv$ source bin/activate
(venv) xxxx@server:~/venv$ ls
bin  include  lib  lib64  pyvenv.cfg  share
(venv) xxxx@server:~/venv$ which python
/home/xxxx/venv/bin/python

まずはpipのアップデート

(venv) xxxx@server:~/venv$ pip install -U pip
Collecting pip
  Downloading pip-21.1.2-py3-none-any.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 4.0 MB/s
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 20.0.2
    Uninstalling pip-20.0.2:
      Successfully uninstalled pip-20.0.2
Successfully installed pip-21.1.2

あとは色々モジュールを入れたりすれば良いですが、折角なので最新バージョンを使用出来るようにと

こちらを参考にpyenv仮想環境を構築した。

git clone https://github.com/pyenv/pyenv.git ~/.pyenv
cd ~/.pyenv
git pull

下記のように環境変数を設定するよう.profileを書き換えて再ログイン

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.profile
echo 'eval "$(pyenv init --path)"' >> ~/.profile

pyenv install -l | grep 3.9
  3.9.0
  3.9-dev
  3.9.1
  3.9.2
  3.9.3
  3.9.4
  3.9.5

最新は3.9.5なのでこれをインストール

pyenv install 3.9.5

なんか色々エラーが出たらコンパイルのためのライブラリが足らんようです。当方の場合はbz2が足りなかったので、

sudo apt install -y libbz2-dev libsqlite3-dev

あとググって足らなさそうなものも入れておくと、無事インストール終了

pyenv global 3.9,5   -----  3.9,5 を使用する
pyenv global system  -----  システムにインストールされているバージョンを使用

python -V

バージョン確認して無事変更されていたら、さらにvenvによる仮想環境も構築しておく

python -m venv venv
cd venv
source bin/activate
python -V

deactivate

こっちの方がライブラリが探しやすいが、pyenvで最新版のpythonが使う環境も欲しいということでの2本立てとしてみた。ライブラリ何度も入れないといけなさそうだけど、色々体で覚えていけそうw

サーバー設定作業メモ

何をやったか忘れないように、メモメモ記事を残すことにした。これも投稿数稼ぎかなw

ポータルサイト http://www.marochanet.org/ の djangoアップデート作業

ウェブユーザでpython仮想環境に入り、まずはpipのアップデート

(venv0) xxx@jagha:~/html/python$ python -m pip install --upgrade pip

次に仮想環境のアップデート可能なモジュールリストをとる(一部表示)

(venv0) xxx@jagha:~/html/python$ pip list -
Package                Version Latest Type
---------------------- ------- ------ -----
……
Django                 3.0.8   3.2.4  wheel
django-bootstrap4      2.2.0   3.0.1  wheel
django-hitcount        1.3.2   1.3.3  wheel
django-tinymce         3.0.2   3.3.0  wheel
……

他にもリストアップされたモジュールを全てアップデートする

(venv0) xxx@jagha:~/html/python$ pip install -U (module name)

ここで、リストには無いがデータベースエンジンとの接続に必要なmysqlclientのアップデートに失敗。

これに関してはpython側のライブラリが不足していたため下記コマンドをrootで打って、ライブラリをインストールする

apt-get install python3-dev libmysqlclient-dev

無事mysqlclientのアップデートに成功して終了。

メールボックス整理ツール

本サーバーでは個人の興味や勉強を兼ねてメールサーバーを運用している。昔はプロバイダメールはPOPで端末に落としてくるのが主流で、例えば家と職場、携帯電話で同じ受信メールを処理することが難しかったし、Exchangeを始めIMAPも使われ始めたが、サーバー負荷が高いため普通のプロバイダでは利用できない場合が殆どだった。今ならフリーのアカウントなどWEBメールを初めとして受信メールをサーバーを置くタイプが多くなってきた。

私が使用しているプロバイダメールも今はWEBメール対応でサーバーにメール本体を置くことが出来るが、やはりPOPがデフォルトのようだ。そこで、まだPOPしか使えない頃から、外部にサーバーを立ち上げて(一昔流行ったおうちサーバーや、現在の当方のような「さくらVPS」)プロバイダからのメール自動転送(昔はPOP)を受けてIMAPサービスを行っている。

サーバーの引越においてもメールデータの移行も必要であった。引越ついでにサーバー上のユーザーのメールボックス形式をmboxからIMAPとの親和性の高いMaildir形式に移行する。二つの形式には大きな違いがあり、

  • mboxのメールボックスは巨大な1ファイル、Maildirはメール1通1ファイル
  • mboxのメールボックスフォルダ階層はファイルシステムに準ずる、Maildirはフォルダの階層はピリオドで接続した構造で表現され、ファイルシステム的には一階層である
  • mboxの受信トレイは/var/spool階層のユーザー名ファイル、Maildirは各ユーザーディレクトリのMaildir直下に配信される
  • どちらも漢字フォルダ名はutf-7で、端末では普通読めない。

そのあたりの作業を簡単に行えるような行き当りばったりツールをまたpythonで作成した。pythonのmailboxライブラリを使用するとmbox形式やMaildir形式のメールボックスを操作することが出来、相互に移動したりフォルダに振り分けたり出来る。というライブラリお任せで作成したツール「mailboxutil」についてまた追々と解説・覚書きを投稿したいと思う。

このツールをつかってメールボックス移行を行ったのは実際には前のサーバーで約1年前CentOS6からCentOS8にOS変更した時でした。まぁ、話がややこしくなるので、今回やったことにさせてくださいw
ていうか、このタイミングでCentOSサポート終了のお知らせは正直凹みました。。。時間を返せーー!と。
(CentOS同士でもメジャーバージョンを一個飛ばしということもありアップグレードインストールは諦めて、バックアップ→新規インストール→データリストアをやっていたのでした。。。)