金魚飼育

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

第一世代は卵を産んでくれたあとすぐに全滅してしまったが、これは寿命と環境の影響かなと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同士でもメジャーバージョンを一個飛ばしということもありアップグレードインストールは諦めて、バックアップ→新規インストール→データリストアをやっていたのでした。。。)

gzipモジュール組込み

主にSMTPへの不正アクセスを監視してファイヤーウォールにブラックリストを追加するpythonプログラム(blockset.py)はサーバー引越前より使用していたが、それまでに集計した不正アクセスIPアドレスリストは引越後も使用して対応していた。

リスト自体は5年くらい前からのものでかなり膨らんで来たしもう既に状況は変わっているかも知れないため、サーバーIPアドレスも変わったという機会もあり最初から収集を始めることとし、一度ブロックリストを空にしてみた。2~3日は特におかしなアクセスは無く油断していたら、夕べ辺りに大量にSMTPへログインアタックがいらっしゃいましたので下記に晒します。

root@jagha:~# blockset.py -u
use defaule.
New record : 31.210.20.7 (13)
New record : 31.210.20.18 (10)
New record : 31.210.20.23 (11)
New record : 31.210.20.39 (15)
New record : 31.210.20.41 (6)
New record : 31.210.20.54 (7)
New record : 31.210.20.93 (7)
New record : 31.210.20.109 (9)
New record : 31.210.20.111 (14)
New record : 31.210.20.155 (13)
New record : 31.210.20.162 (15)
New record : 31.210.20.173 (11)
New record : 31.210.21.3 (6)
New record : 31.210.21.4 (6)
New record : 31.210.21.9 (6)
New record : 31.210.21.76 (5)
New record : 31.210.21.82 (13)
New record : 31.210.21.96 (12)
New record : 31.210.21.195 (15)
New record : 31.210.21.220 (15)
New record : 31.210.21.235 (6)
New record : 31.210.21.242 (7)
New record : 31.210.21.243 (12)
New record : 45.133.1.22 (15)
New record : 45.133.1.50 (11)
New record : 45.133.1.58 (7)
New record : 45.133.1.73 (13)
New record : 45.133.1.100 (13)
New record : 45.133.1.102 (14)
New record : 45.133.1.109 (14)
New record : 45.133.1.127 (11)
New record : 45.133.1.138 (8)
New record : 45.133.1.192 (15)
New record : 45.133.1.203 (8)
New record : 45.133.1.204 (8)
New record : 45.133.1.206 (13)
New record : 45.133.1.214 (15)
New record : 45.133.1.218 (15)
New record : 45.133.1.239 (15)
New record : 45.133.1.241 (12)
New record : 45.133.1.242 (12)
New record : 45.133.1.247 (8)
New record : 45.144.225.54 (15)
New record : 45.144.225.95 (13)
New record : 45.144.225.204 (9)
New record : 45.144.225.205 (7)
New record : 45.144.225.206 (7)
New record : 136.144.41.70 (7)
New record : 136.144.41.87 (12)
New record : 136.144.41.132 (6)
New record : 136.144.41.162 (8)
New record : 136.144.41.166 (8)
New record : 136.144.41.181 (15)
New record : 136.144.41.209 (8)
New record : 195.133.40.31 (8)
New record : 195.133.40.34 (15)
New record : 195.133.40.41 (7)
New record : 195.133.40.63 (7)
New record : 203.159.80.60 (12)
New record : 203.159.80.61 (15)
New record : 203.159.80.77 (6)
New record : 203.159.80.190 (12)
update ufw before.rules
Firewall reloaded

こちらをネットマスク24ビットでくるめると、意外に同じノードからのご来店が多く、

31.210.20.0/24  <=  31.210.20.0
31.210.21.0/24  <=  31.210.21.0
45.133.1.0/24  <=  45.133.1.0
45.144.225.0/24  <=  45.144.225.0
136.144.41.0/24  <=  136.144.41.0
195.133.40.0/24  <=  195.133.40.0
203.159.80.0/24  <=  203.159.80.0

これだけになったので、この辺りの方々が迷惑なドメインということで一括ブラックリストとした

あと、もう一点、先日のlessコマンドにならってgzip圧縮されたログファイルも普通に解析できるように仕様追加した。cron起動されるlogrotateでまだ解析していないログファイルが圧縮アーカイブされてしまう可能性がある。

pythonのgzipモジュールを使用すると通常ファイルと同じように普通に読み書き出来るファイルハンドルが生成される。with構文を使用してファイル操作を行っている部分を下記にように変更した。

import gzip
import re

・・・・
    with open(args.logfile, 'r', encoding='utf-8') if not re.search('\.gz$', args.logfile) else gzip.open(args.logfile, 'rt') as fh:
        for line in fh:
            ・・・・

with構文の中でインライン条件分岐を行い、末尾が’gz’だった場合はgzipでオープンするという内容。

この方法、他の用途のファイル読み込みでも応用が考えられる。もう一つ分岐を増やして、ファイル名が空白であった場合は標準入力(sys.stdin)とするなども出来そうだ。

lessコマンドの覚え書き

CentOSからUbuntuにサーバー引越して、いろいろ違いがあった場合その都度対策している。今回は特に困っているわけでは無いが、コマンドラインツールのlessについて、lessはテキストファイルの内容をページ送りで閲覧することが出来るビュアーで間違って編集してしまわない安心感とお手軽さで昔から常用しているツールだ。

大昔は無かったと思うが、CentOSで運用しているとき。ファイル名の代わりに間違ってディレクトリ名を渡してしまった時。エラーでなく、そのディレクトリのファイル名一覧(ls -la の結果)が表示されるようになっていた。これが以外に便利で、ファイルがメチャメチャ入っているディレクトリとかザーッと眺めるのに丁度良い機能だった。

とは言ってもそんなに使う事もないので、忘れたまま先日のサーバー引越&OS変更(CentOS→Ubuntu)を行なった後に、lessを使うとディレクトリ一覧機能が無くなっていた。CentOSのマシンもまだ生きているので改めて試してみるとこちらは引数にディレクトリを与えることで、ファイルの一覧が出来ていた。ディストリビューションごとの機能の違いなようだがlessなんていうレガシーがツールに今更機能の差があるのは考えにくいので、設定関係で調査してみた。

どうやら、lessには前処理を行なうlesspipe(.sh)というシェルスクリプトがあり、ここで圧縮ファイルの展開などを行なっていたようだ。

/usr/bin/lesspipe(.sh)

CentOSとUbuntuでこれらのファイルを比較したところ、CentOSの方には下記のような引数がディレクトリだった場合の処理が入っている。

if [ -d "$1" ] ; then
        ls -alF -- "$1"
        exit $?
fi

これをUbuntuの方にも記載することで、無事ディレクトリリストを閲覧することが出来るようになった。

/usr/bin/lesspipeを直接編集してしまったので、今後アップデートで元に戻ってしまった時のことを考えての覚え書き・・・・とφ(`д´)メモメモ…