OpenCVでサイコロのでた目の数をカウントする

概要

OpenCVでサイコロのでた目の数をカウントしたくなった。 ボードゲームを少し電子化してよりゲームを面白くするために使いたいと思っている。

実装

条件

サイコロを上から見る場合に限定して実装する。(立体的にみてどの面が上になるのかを判定するのが難しそうだっため)

手順

  • OpenCVで画像からまずサイコロの四角を抜き出してくる。
  • すべてのサイコロに対して以下の処理を行う。
  • 抜き出してきたサイコロ画像の中から丸(サイコロの目)を探して丸の数を数える。
  • 最後に目の数を合計して出力する。

こうなった。 github.com

元の画像 f:id:KYudy:20180128200657j:plain

サイコロが写っている部分だけを抜き出して、目の部分を赤色で示した。 f:id:KYudy:20180128200608j:plain

出た目の数は以下のように印字される。

sum is 10 [6, 4]

Ansibleでファイルのバックアップを作成する

Ansibleでファイルをバックアップしたいことがある。 失敗することを考えるとバックアップは一度だけ実行したい。 シェル上ならばcpするときに -n を指定すれば2回め移行は上書きされないことを保証できる。

       -n, --no-clobber
              do not overwrite an existing file (overrides a previous -i option)

Ansibleでも同じようにshellモジュールで実行すればよいという話もあるが、 可能な限りshellを避けるべきだと思う。 --diff で差分でないし。

そこでマニュアルとにらめっこして考えだしたのが以下となる。 http://docs.ansible.com/ansible/latest/copy_module.html

      copy:
        src: /path/to/src_file
        dest: /path/to/dst_file
        remote_src: yes
        force: no

remote でサーバ上のファイルを指定してバックアップできる。 force で上書きしないようにできる。

ansible iptables `state=absent` が動かない。

ansibleのモジュールiptablesで'state=present'が機能しない。

ansibleでiptablesをメンテナンスしようとおもい、以下のモジュールを利用したが、どうにも state=absent が動かない。 iptablesモジュールのソースを追ってみたところ、以下のようにchangedを判定しているのだが、

# /usr/lib/python2.6/site-packages/ansible/modules/extras/system/iptables.py

def check_present(iptables_path, module, params):
    cmd = push_arguments(iptables_path, '-C', params)
    rc, _, __ = module.run_command(cmd, check_rc=False)
    return (rc == 0)

この -C(--check) はどうやら最近のiptablesしか持っていないようで、これがうまく機能しないため、changedは常にfalseになるようだ。

$ cat /etc/redhat-release
CentOS release 6.4 (Final)
$ sudo iptables --check INPUT -p tcp -s 0.0.0.0/0 -d 0.0.0.0/0 -j REJECT --destination-port 25
iptables v1.4.7: unknown option `--check'
Try `iptables -h' or 'iptables --help' for more information.

ソースを追わないと気づけないのが問題だと思う。↓

    return (rc == 0)

css changes not synced for heroku django based app on virtualbox shared folder.

概要

virtualbox上でherokuのアプリを作っていたのだが、共有フォルダにソースを置いてホストOS上からCSSをいじるとなぜかうまく反映されないため困った。 Webサーバを再起動したりキャッシュっぽいファイルを手当たり次第に消したりしてみたが、いっこうにうまくいかない。 gunicornやwhitenoiseを疑って見たものの特に関係なさそうだった。

結論としてはherokuもgunicornもwhitenoiseもdjangoも関係なかった。 virtualboxのバグらしい。 www.vagrantup.com

ホストOSではなくクライアントOSからファイルを編集すると問題なく反映されるあたりで疑って調べ始めてすぐわかったのでよかった。

対応方法

gunicornを使っている場合は以下のように--no-sendfileをつけて起動すればsendfileを無効化でき、バグを回避できる。

$ cat Procfile 
web: gunicorn proj.wsgi --no-sendfile

PostfixのmaillogのFromとToを結合する。

PostfixのmaillogのFromとToを結合する。

Postfixのログを調べるときに一つのメールの行方を追うだけならすごく簡単だが、 複数まとめて検索したいときに面倒くさいのはログ上のFromとToが別の行になっていることだろう。

Feb  9 17:32:04 server001 postfix/qmgr[27385]: 000E21A124F: from=<test@example.com>, size=2414, nrcpt=2 (queue active)
Feb  9 17:32:04 server001 postfix/smtp[7790]: 000E21A124F: to=<test@example.com>, relay=1.1.1.1[1.1.1.1]:25, delay=0.11, delays=0.04/0/0/0.06, dsn=2.0.0, status=sent (250 2.0.0 589c29044d9318 Message accepted for delivery)
Feb  9 17:32:04 server001 postfix/smtp[7790]: 000E21A124F: to=<test@example.com>, relay=1.1.1.1[1.1.1.1]:25, delay=0.11, delays=0.04/0/0/0.06, dsn=2.0.0, status=sent (250 2.0.0 589c29044d9318 Message accepted for delivery)
Feb  9 17:32:04 server001 postfix/qmgr[27385]: 000E21A124F: removed

ちなみに一つのメールのログはqueueidで紐づいている。 この例の場合は 000E21A124F がqueueidである。

泥臭い方法で実装するならば、queueidを全て抜きだして、その数だけgrepして結果を加工する方法がある。 当然ながら時間がかかりすぎる。

join コマンドを利用することでもう少し賢くできる。

こんな感じにする。

$ sudo grep ': from' /var/log/maillog | awk '{print $6,$7}' | sort > from.txt
$ sudo grep ': to' /var/log/maillog | awk '{print $6,$7,$12}' | sort > to.txt
$ join from.txt to.txt

fromもtoも$6にはqueueidが入る。 joinは先頭が一致する行同士を結合してくれる。

問題としては、queueidは使いまわされることがあり、1日ぐらい経つと同じものが使われていることがある。 毎日ログをローテションするなりすれば良いと思われる。その場合に日をまたいだメールとかがあると取りこぼすのも注意が必要。 そしてその場合もqueueidに日付文字列を加えれて複数の日付のログを一度に処理することで問題が解決される気がする。

.ssh/configに記載されたホストをタブ補完する

.ssh/configに記載されたホストをタブ補完する

概要

ssh実行時に.ssh/configに記載されたホスト名を補完したいなぁとおもったのでやってみた。

同じことは他の方もやっていたので、それを参考にした。その結果ほとんどオリジナリティはない。

あくまで一例として。

参考

.ssh/config 設定内容(サンプル)

.ssh/config

HOST host001
        HOSTNAME 1.1.1.1
HOST host002
        HOSTNAME 1.1.1.2

.bashrcへの追記内容

.bashrc

_ssh_comp_func () {
  local cur
  cur=${COMP_WORDS[COMP_CWORD]} 
  COMPREPLY=($(grep 'HOST ' .ssh/config | awk '{print $2}' | grep "${cur}"))
}

complete -F _ssh_comp_func ssh

curに現在の補完中のホスト名が入る。

補完が進むと補完候補が少なくなるように grep "${cur}" している。

わざわざダブルクオートで囲んでいるのはcurに何も入っていないときにエラーが出るのを防ぐためである。

これを応用すると結構好き勝手補完できるようになって便利かもしれない。

abrtdを使用している時は `ulimit -c` は効かない

abrtdを使用している時は ulimit -c は効かない

背景

Postfixの認証を担っているsaslauthdがクラッシュしてコアを吐いたのだが、設定が悪く保存されなかった。 再発した時にちゃんとコアが保存されるように設定する過程でネットで調べた情報が一部自分の環境(CentOS release 6.6)には適用されないことがわかった。

課題

表題の通り ulimit -cによるcore file sizeの上限が適用されないことが分かった。 soft limitの値が0、つまりコアを保存しない、という設定は適用されない。

結論

結果から言えば、CentOSはコアをabrtdというデーモンが受け取ってファイルに書き込む設定になっている。 abrtdが生成するコアのファイルサイズはulimitが指定する値は適用されない。

説明

以下のようにsaslauthdの Max core file size のsoft limitは0、hard limitはunlimitedである。 ということは本来saslauthdのコアは破棄されることになる。

$ ps aux | grep saslauth[d]                                                                                                            
root      2710  0.0  0.0  69948  1088 ?        Ss   20:06   0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a httpform -c -t 60
root      2712  0.0  0.0  69948   772 ?        S    20:06   0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a httpform -c -t 60
root      2713  0.0  0.0  69948   772 ?        S    20:06   0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a httpform -c -t 60
root      2714  0.0  0.0  69948   772 ?        S    20:06   0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a httpform -c -t 60
root      2715  0.0  0.0  69948   772 ?        S    20:06   0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a httpform -c -t 60
$ sudo cat /proc/32411/limits | grep core
Max core file size        0                    unlimited            bytes  

しかし以下のように SIGABRT をプロセスに入れるとコアが生成される。

$ kill -ABRT 2710 
$ sudo tail /var/log/messages                                                                                                           
Jan 23 20:08:24 test001 abrtd: Directory 'ccpp-2017-01-23-20:08:24-2710' creation detected
Jan 23 20:08:24 test001 abrt[2756]: Saved core dump of pid 2710 (/usr/sbin/saslauthd) to /var/spool/abrt/ccpp-2017-01-23-20:08:24-2710 (1101824 bytes)

生成される事自体は問題ないが、 ulimit -c の値が適用されないのは気持ちが悪い。

調べた過程は省くがCentOSの場合は以下のような設定が適用されているため効かないようだ。

$ cat /proc/sys/kernel/core_pattern 
|/usr/libexec/abrt-hook-ccpp %s %c %p %u %g %t e

これでabrtdにコアが渡されている。

https://linuxjm.osdn.jp/html/LDP_man-pages/man5/core.5.html

このファイルの最初の文字がパイプ記号 (|) であれば、 その行の残りの部分は実行するプログラムとして解釈される。 コアダンプは、ディスク上のファイルに書き込まれるのではなく、 プログラムの標準入力として渡される。 以下の点に注意すること。 

このあたりでコアを標準出力でパイプを介してabrtdに渡しているから core file size が効かない(ファイルじゃないから)ということが薄々わかる。

あとはRedhatのabrtdのマニュアルを少し読み込むと以下のような記載がある。 https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/sect-abrt-configuration-abrt.html

MakeCompatCore = yes/no
    This directive specifies whether ABRT's core catching hook should create a core file, as it could be done if ABRT would not be installed. The core file is typically created in the current directory of the crashed program but only if the ulimit -c setting allows it. The directive is set to yes by default. 

Coreとの互換性をもたせるオプション MakeCompatCore がyesの場合は ulimit -c が許可する場合だけコアを吐くようにできるとのこと。 つまり互換性を設定で有効にしない限り core file size の制限は効かないのが普通の動作だよ、ということである。

よく見ると、デフォルトでyesって書いてあるけど・・・? まぁいいか。