きつねたぬきだし

ちょっとしたメモ代わりに。

シェルから syslog にメッセージ

logger なる便利なコマンドがあることを知らず。

$ logger 'こんにちはこんにちは!'

これで OK

$ logger -t 'タグも付けられます!' 'こんにちはこんにちは!'

他は man してください。

ちなみに

syslog-notify なる、おもしろそうなプロジェクトが。

http://code.google.com/p/syslognotify/

syslog から、 OS X などの Notification Center ( Mountain Lion から 右側にあるアレ ) にメッセージを送れるそうな。

rsyslog あたりで、サーバの出力を拾って、 Priority の高いメッセージだけ、 Notification Center に飛ばすとかできそう。

さすがに、 I/O heavy な用途では redis とかの方が良いでしょうが、 syslog 絡みでカジュアルなロギングやりたいなら、面白そうですよね。

また、単にシェルから Notification Center に送りたいだけなら、

Terminal Notifier

https://github.com/alloy/terminal-notifier

が良いです。 gem で入ります。

$ terminal-notifier -message 'えい'

長そうなプロセスをバックグラウンドで起動して、結果だけ知りたい時とかに使えます。 オプションが Long Option っぽくないのが気になりますが。

netstat で Unix Domain Socket の一覧を表示する

語弊を恐れずに、

「インターネットじゃなくてファイルの方でつながってるソケット」

を netstat で表示する。

GNU/Linux

netstat -lt --protocol=unix

BSD 系 (OS X 含む )

netstat -f unix

使い道

  • ネットワークの勉強を基本からやりたいよ!
  • Unix ってそもそもどうなってるの?
  • 超うっかり、 mysql.sock を消しちゃった!
  • JDBC - MySQL の接続でハマった!
  • Unix Domain Socket のプロキシを作りたい!

【解決編】Django の ORM の Date でハマってる

そもそも

そもそも MySQL のクエリのログくらい、見ましょう。

書き忘れていた場合は、以下の行を my.cnf の [mysqld] に記述します。 パスなどはもちろん、各々の環境に合わせてください。

log = /var/log/mysql/mysql-query-history.log

ログを見る

実際に発行されたクエリ

SELECT `sampleapp_bar`.`id`, `sampleapp_bar`.`foo_id` FROM `sampleapp_bar` INNER JOIN `sampleapp_foo` ON (`sampleapp_bar`.`foo_id` = `sampleapp_foo`.`id`) WHERE `sampleapp_foo`.`date` > '2013-01-01' LIMIT 21

QuerySet.query.str() で出力されたクエリ

SELECT `sampleapp_bar`.`id`, `sampleapp_bar`.`foo_id` FROM `sampleapp_bar` INNER JOIN `sampleapp_foo` ON (`sampleapp_bar`.`foo_id` = `sampleapp_foo`.`id`) WHERE `sampleapp_foo`.`date` > 2013-01-01

全然、違いますね。 実際に発行したほうだと、 LIMIT 句までついています。 QuerySet.query.str() が表示するクエリは、あくまで目安でした。 そもそも QuerySet の段階では実行されてない & どの DB にアクセスするかすら決まっていない のだから、 query が返す値が目安にしかならないのは当たり前ですね。

関係ないこと

gt, lt, gte, lte を使うより、 startswith, endswith の方が良さげです。 期間の時も、 range を使うと、 BETWEEN になるので、そっちのほうが良いかも。

Django の ORM の Date でハマってる

バージョンとか

まだ解決していないので、ざっくりした記事です。

(追記 2013/01/15 解決しました!現在記事作成中です。)

解決したら、ざっくりした生地をふわふわした記事に焼き上げます。

バージョンは以下の通りです。

検証したこと

こんなモデルを Django で作りました。

from django.db import models


class Foo(models.Model):
    date = models.DateField()


class Bar(models.Model):
    foo = models.ForeignKey(Foo)

さっそく、

python manage.py syncdb

して、

python manage.py shell

で試してみましょう。

>>> import sampleapp.models
>>> _query = Bar.objects.filter(foo__date__gt='2013-01-01').query
>>> print(_query)
SELECT `sampleapp_bar`.`id`, `sampleapp_bar`.`foo_id` FROM `sampleapp_bar` INNER JOIN `sampleapp_foo` ON (`sampleapp_bar`.`foo_id` = `sampleapp_foo`.`id`) WHERE `sampleapp_foo`.`date` > 2013-01-01 
>>>

見ての通り、 2013-01-01 にクオートがありません。非常に怖いですね。 実際にデータを処理してみましょう。

以下のように、 1 件のデータを入れてみました。

bar

idfoo_id
11

foo

iddate
12012-03-01

このデータだと、 2013-01-01 は 2012-03-01 よりも大きい(新しい)ので、ヒットしないはずです。

しかし、上のクエリを直接実行してみると、bar の id=1 がヒットします。 なぜなら、 2013-01-01 が評価され、 2013 - 1 - 1 = 2011 となるからです。

クエリ中の日付をシングルクオートで囲み、 '2013-01-01' とすると、正しい 0 件ヒットとなります。 MySQL 側の仕様としては、日付リテラルの挙動はこれで正しいはずです。

さらにこれは query がおかしいだけではなく、実際に QuerySet からの参照時も、このような動作になっているようです。 また、比較用の値を、 DateField の date や datetime.date にした場合の動作も同様でした。 (それぞれ、検証用のコードはまだ整理しておりません。)

date だけでなく、 datetime でも比較してみると面白いかもしれないです。

Django について自分の理解が足りていないだけなのかもしれず、ちょっと困惑中です。

詳細をご存知のかたおられましたら、ツッコミよろしくお願いします。

【ハマった】 ImageMagick で作成した画像の色表示がブラウザによって異なる。

ImageMagick とは

画像変換に使う十徳ナイフ的な CLi です。

今回の問題

ChromeSafari とで、 変換した PNG 画像の色合いが違った。 それどころか、置換したはずの色とも違う色が表示されていた。

原因

画像のカラープロファイルがない場合、ブラウザごとに処理が違う。 Safari: スルーする Mobile Safari: 推測する Chrome: 独自の置換をする

( 要出典 )

対策

convert コマンドのオプションに

-set colorspace sRGB

を明示的に加えて、色空間を指定する。

例:

convert -set colorspace sRGB -fill '#FFCCFF' -opaque '#FFFFFF' before.png after.png
# 指定色 #FFCCFF で選択色 #FFFFFF を塗りつぶす。

付記

さらに、モニターのドライバが足りていない場合も、 OS によって処理が異なるので注意。 2 重にめくらましがあると簡単には解決できなくなる。

シェルスクリプトのごく基本的なツッコミ

はじめに

無駄な cat, 無駄な echo を無くすことが大事です。

この記事中では、サンプルのコマンドとして mysql をつかってます。

本来、 mysql なら -e オプションで引数から文字列を入れるほうが綺麗です。

その場合は -BN してやるとバッチモードで同じ出力フォーマットになります。

今回は、「標準入出力」に対するサンプルのため、 e オプションは使用してません。

ヒアドキュメントを使ってもパイプできる

忘れがちですが、 EOT の後にもパイプもリダイレクトも繋げられます。

<<EOT mysql db_name | tail -n 1
SHOW DATABASES;
EOT

無駄な echo しない

無理に一行で書こうとして

echo 'SHOW DATABASES;' | mysql

とかやるくらいなら、

mysql <<<'SHOW DATABASES;'

こっちのほうがいけてる。

先に標準入力が書きたいなら、

<<<'SHOW DATABASES;' mysql

これでも可能。

なぜだかリダイレクトは最後にしか書けないと思い込んでいる人が多い。

複数行コメント

複数行のコメントには : (null command) を使う。

:<<__EOT__
ここにコメント
__EOT__

次のような cat を見ると悲しくなります。

cat >/dev/null<<__EOT__
ここにコメント
__EOT__

デバッグ

デバッグ時には -x オプションで起動すると良い。