以前からたまーにこういうのがあるとうれしいケースがあるなぁと思ってたので作りました。
どういうものかというと、こういう感じで何かstdoutに吐き出すコマンドの前にfcache EXPIRE_SEC
というのを付け足して実行すると、初回はコマンドを実行して結果をファイルに保存しつつstdoutにも出力します。
$ fcache 10 curl -s example.com
hoge
次に、同じfcache
コマンドを叩くと、保存されているキャッシュファイルの時刻を見て、expire時刻を過ぎてなければ単にそのファイルの中身をstdoutに吐き出して終了します。
$ fcache 10 curl -s example.com # 実際はcurlは実行されない
hoge
expire時刻を過ぎていれば初回と同じ動きをしてキャッシュを更新してくれます。flock
を使って、読み込みだけなら共有ロックで並列に、書き込みが発生する時には排他ロック、みたいな処理をしてます(が何分まともな排他制御書いたことないのできっとバグってます。。。)
何の役に立つの?
特に監視の処理の中で、ほぼ同時に並列で1つのAPIを叩く監視項目があった時に、みんなが同じAPIを叩くのは非効率だなぁと思った時に効果があります(つまりニッチ)。何も気にせずfcache
コマンドを並列に実行すれば、最初の人がAPIを叩いてキャッシュしてくれて、あとの人はキャッシュを利用してくれます。
例えばZabbixという監視ソフトにはUserParameter
というagent側でコマンドを実行して数値を返す、みたいなのが定義できます。
$ curl -s localhost
aaa 1
bbb 2
ccc 3
$ cat /path/to/zabbix_agentd.conf
UserParameter=example.key[*],curl -s localhost | grep $1 | cut -f 2
上の様な設定をしたサーバがあったとすると、zabbix_get
でaaa
,bbb
,ccc
の値が取れます。
$ zabbix_get -s server -k example.key[aaa]
1
$ zabbix_get -s server -k example.key[bbb]
2
$ zabbix_get -s server -k example.key[ccc]
3
ただし、これだと3回curl
が呼ばれます。もしcurl
を減らしたいなら、1つのitemでスクリプトを実行してその中で1回だけcurl
してから全てのキーについてzabbix_sender
で送る、とかも考えられます。
$ cat /path/to/zabbix_agentd.conf
UserParameter=example.key,/path/to/script # 中でzabbix_senderを複数実行
fcache
を使うとシンプルに実現できます。これならキャッシュの有効期間中はcurl
は叩かれませんし、configも素直です。
$ cat /path/to/zabbix_agentd.conf
UserParameter=example.key[*],fcache 10 curl -s localhost | grep $1 | cut -f 2
おわりに
適当に作った上に、自分で使ってるわけでもないので自己責任でご利用下さい。こういうコンセプトがあってもおもしろいよねという提案がしたかったのと、ちょうどpythonの勉強がしたかったので、自分的には満足です。