swatchをfluentdに連携させる

swatch(Simple Log Watcher)は昔からあるログ監視ツールらしい。

詳細は置いておいて、このswatchの出力をfluentdに送りたい。なぜならばデフォルトでswatchが出力できるのはmailと標準出力なので、サーバの台数が増えてくると管理できなくなる(メール100通とか毎日見たくないし、標準出力をターミナル100個見続けるとか無理)

幸いswatchは出力をpipeすることができる。
このpipeとfluent-catを組み合わせることでswatchの出力をfluentdに送出できる。
実際に動かすところまで実践してみたので、設定内容をメモする。

gist.github.com

pipeの引数にforward_fluent.shを指定している。
このシェルは下記の通り、受けた標準出力をfluent-catに渡すものだ。
tagを指定するのと、swatchの出力をfluent-catの入力フォーマット(デフォルトではjson)に変換する必要があるので、シェルを一つかましている。

forward_fluent.sh

gist.github.com

実行

$ swatch --daemon -c swatch.conf -f test.log --pid-file=pid

実行すると、echoもしているので色分けされた出力が標準出力に表示される。
また、同時にfluentdにも送信されているのを確認した。

以上

leapmotionでキー入力がしたいのでプロトタイプを作ってみた

勢いでleapmotionを新宿のヨドバシカメラで買ってきてしまった。
実は前々からジェスチャーで文字入力をやってみたかった。

環境

どのような入力を実現するか

手の指を一本折り曲げた状態で手を左右上下前後に動かし、
どの指が曲がっているかと、手を動かしている方向の組み合わせを入力パターンとする。
とりあえず片手だけにしたので、指の本数(5) x 左右上下前後(6) = 30通りの入力が可能。
アルファベットは網羅できる。

イメージ↓
f:id:KYudy:20160504165028p:plain

ソースコードは以下のとおり。leapmotionのAPIが非常によく出来ていて、簡単につくることができた。

gist.github.com

動いているところ↓
f:id:KYudy:20160504165608p:plain

正直全然実用できないが、形にはなった。

perlワンライナー集計処理

以下の様なテキストを入力として受け、出力を合計値にしたい。

a 10000
b
c 33
b 100
a 3993

出力

c 33
a 13993
b 100

シェルスクリプトで実装する方法も考えたが、なんだか面倒なので、
なれないPerlワンライナーにチャレンジ

以下を参考にした。
Perlワンライナー覚書」tossh
http://qiita.com/tossh/items/f8d448c0c039f68c0ea3

結論としては以下とすればよい。

$ cat << EOF | perl -anle '$count{$F[0]}+=$F[1]; END{foreach(keys(%count)){print "$_ $count{$_}"}}'
> a 10000
> b
> c 33
> b 100
> a 3993
> EOF
c 33
a 13993
b 100

勉強したこと

perlワンライナーを各ときはオプションが重要

-a AWK的な感じで入力を区切り文字(スペース)で分割して変数で扱えるようにする。
-n インプットを一行ずつ処理する
-l printの文字列に改行を明示的に書かなくてよい
-e ワンライナーを指定するために必須

ハッシュは初期化しなくても良い。既知のキーが入ってなくても参照できるし、+=を使った場合に0が入っていたかのように振る舞う。
Perlはよくわかっていないが、ワンライナーのために頑張っている感がある。

「ls: 引数行が長すぎます」を回避する

ls: 引数行が長すぎます

ファイルが大量にあるディレクトリをワイルドカードを使用してlsすると以下のように怒られる。

  • ダメな例
$ rm /hoge/fuga/??/*/*/hige/
ls: 引数が多すぎます 

エラーの文字列でググると、回避方法としてfindとxargsの組み合わせが一般的らしい。 http://moviesearch1.blog15.fc2.com/blog-entry-8.html

【例】
find /var/www/html/movie-search/cache/ -name "*.cash" -print0 | xargs -0 rm -rf

エラーはシェルがワイルドカードを展開してコマンドに渡す際に上限値を超える場合に発生する。

上記の例だとfindの-nameで渡しているワイルドカードはシェルでは解釈されず、findコマンドが展開を担当しているので、問題を回避できる。

「ダメな例」の場合はこの方法を使えない。なぜなら、ディレクトリ階層がネストしていて、それを-nameできれいに吸収できないからだ。 やるとして以下の様な汚い感じになるだろう。

  • 回避例1
find  /hoge/fuga/ -name "??/*/*/hige/" -print0 | xargs -0 rm -rf

直感的じゃないし、余計なディレクトリを探しに行くだろう。

更に調べると、どうやらechoとxargsの組み合わせで回避できるらしい。 http://x68000.q-e-d.net/~68user/unix/pickup?xargs

echo はシェルの内部コマンドのため ARG_MAX の制限を受けない。一方、xargs は ARG_MAX の値を把握していて、引数が ARG_MAX を越えそうになると

バッドノウハウ感があるが採用する。

echoとxargsの組み合わせで「ダメな例」を回避するには以下のようにする。

  • 回避例2
$ echo /hoge/fuga/??/*/*/hige/ | xargs rm -rf

回避例1にくらべてだいぶマシなのがわかる。

xargs -I{}を使うとき

上記の例のrmをmvに書き換えるともう一つの問題に直面する。

  • ダメな例2
$ echo /hoge/fuga/??/*/*/hige/ | xargs -I mv {} {}.bk
xargs: 引数行が長すぎます

上記ではうまくいっていたxargsだが、-I{}を使用した途端が引数が長すぎると文句を行ってきた。 これはいかに??

困ったらmanを読む。以下のように書いてある。 http://linuxjm.osdn.jp/html/GNU_findutils/man1/xargs.1.html

-I replace-str
    xargs が実行するコマンドに対してユーザが引き数 (すなわち initial-arguments) を指定したとき、その initial-arguments 中にある replace-str の部分すべてを、標準入力から読み込んだ名前で 置き換える。 なお、空白は、クォートされていない場合も、入力される項目の区切りには ならない。区切り記号は改行文字だけになるのだ。 -x と -L 1 が自動的に設定される。 

「区切り記号は改行文字だけになるのだ」 サラッと書いてあるが、驚きである。 echoはファイル名を空白区切りで返すので、すべてのファイル名を一つの文字列として扱うためエラーとなる。 手っ取り早く解決するには、空白を改行に書き換えればよい。

$ echo /hoge/fuga/??/*/*/hige/ | tr ' ' '\n' | xargs -I mv {} {}.bk

この一文だけ見ると、なぜtrがいるのかわからない謎シェルになってしまうこと請け合いである。

Postfixがきりの良い時間にアクセスすると遅い

Postfixがきりの良い時間にアクセスすると遅い

背景

ユーザから「cronがキックするスクリプトがメールを送るとPostfixからの応答が遅くタイムアウトが起きている」と報告された。

結論

nslcdのレスポンスが遅いことが原因だった。 きりの良い時間はLDAPのアクセスが多く、負荷が高まるためレスポンスが遅くなっている。 対象のPostfixは動作上LDAPが必要なく、nslcdがLDAPの応答がない場合にさっさとタイムアウトするようにすることで改善した。

調査

最初はmilter、saslauthdを疑っていたのだが、両者を外した状態で検証しても改善しない。 master.cf, main.cfのパラメタも変えてみたが改善しない。 回りくどいことはやめて、straceでプロセスを追ってみた。

$ ps auxww | grep master
root     12984  0.0  0.0 107452   948 pts/1    S+   16:07   0:00 grep master
$ sudo strace -tt -s 2048 -f -p 12984 -t > strace.20151105 2>&1 
1:35:01 clone(Process 9798 attached
[pid 12984] 21:35:01 clone(Process 9799 attached

9799と9788はmasterがcloneを実行して作成したプロセス。

[pid  9799] 21:35:01 open("/lib64/libnss_ldap.so.2", O_RDONLY) = 1

ldapライブラリを読み込んでいる

[pid  9799] 21:35:01 execve("/usr/libexec/postfix/smtpd", ["smtpd", "-n", "465", "-t", "inet", "-u", "-o", "stress=", "-s", "2", "-o", "smtpd_sasl_auth_enable=yes", "-o", "smtpd_sasl_security_options=noanonymous"], [/* 4 vars */]
 <unfinished ...>

9799はmasterからsmtpdに転身する。

9799だけに関して見ると以下のように1秒から14秒まで飛んでいる。

[pid  9799] 21:35:01 munmap(0x7fc9a8b3b000, 34862) = 0
[pid  9799] 21:35:01 socket(PF_FILE, SOCK_STREAM, 0) = 10
[pid  9799] 21:35:01 connect(10, {sa_family=AF_FILE, path="/var/run/nslcd/socket"}, 110) = 0
[pid  9799] 21:35:01 select(1024, NULL, [10], NULL, {9, 999999}) = 1 (out [10], left {9, 999995})
[pid  9799] 21:35:01 sendto(10, "\1\0\0\0\213\23\0\0\7\0\0\0postfix", 19, MSG_NOSIGNAL, NULL, 0) = 19
[pid  9799] 21:35:01 select(1024, [10], NULL, NULL, {59, 999999} <unfinished ...>
[pid  9799] 21:35:14 <... select resumed> ) = 1 (in [10], left {46, 803711})
[pid  9799] 21:35:14 read(10, "\1\0\0\0\213\23\0\0\3\0\0\0", 1024) = 12
[pid  9799] 21:35:14 close(10)          = 0

/var/run/nslcd/socketにデータを送りつけるところで止まっているように見える。 nslcdはLDAPでユーザ情報を引くときに通信するデーモンらしい。 http://arthurdejong.org/nss-pam-ldapd/nslcd.conf.5

Postfixという名前のユーザはローカルに存在するので、LDAPに聞きに行く必要は無いはずだがよくわからない。 /etc/nsswitch.conf上もfilesが優先されていた。

とりあえず、以下のようにnslcdのタイムアウト値を減らしたところ、レスポンスが改善した。

bind_timelimit 2
timelimit 3

ちょっと釈然としないが、よいとしよう。

キーボードってそろそろ進化するべきなんじゃないだろうか

スマホのフリックは好きだ。でもキーボードの入力速度にはかなわない。
いつでもキーボードを持ち運べて、どこでも使えるならキーボードを使うだろうけど、そうはいかない。
キーボードは、まずどこかに置かないと行けないし、幅を取る。

キーボードが現在の形に落ち着いてからしばらく立つんだけど、そろそろ進化するべきじゃないかな?

なんとなく検索していたらkeygloveというものを見つけた。makezine.jp

手袋型のキーボードと呼んだらいいのだろうか。
これならスキー場でも使うこともできるだろう。
ちょっとごてごてしているのがネックだ。

今後に期待。

手のひらキーボードなるものもあるらしいgigazine.net

発送がキーボードから抜けていない気もするけど、応用の幅は広そうだ。
脳に限らず、人体の信号をセンサーにできればいいのだろうけど。
神経から信号を取り、逆にフィードバックを神経に与えるようなもの。失敗すると痛そうだけど。


prosheet.jp
指輪デバイスもある。これはキーボドの代わりにはならないだろうなぁ。

IPの偽装

検証目的で接続元のIPを偽装したい場合にループバックデバイスIPアドレスを変更するという方法がある。
参照:http://thesimplesynthesis.com/post/how-to-spoof-your-ip-address-to-test-geolocation


$ sudo ifconfig lo 218.xxx.xxx.xxx
$ telnet 218.xxx.xxx.xxx 25
$ sudo less /var/log/maillog
Aug 24 17:59:03 dev001 postfix/smtpd[27156]: disconnect from unknown[218.xxx.xxx.xxx]
Aug 24 17:59:21 dev001 postfix/smtpd[27160]: connect from unknown[218.xxx.xxx.xxx]