python/tornadoで小規模なサーバーアプリを動かす際、ログファイルを監視して特定の文字列が出現した時に任意のコマンドを動かしたい要求が生じたので適当にスクリプトを書いてみました。
要件としては
- 追記のみ行われるログファイルに対し、追記が行われたタイミングで追記部分を外部スクリプトに1行ずつ渡す
- 複数行1度に追記された場合でももれなく渡す
- ログローテーションは考慮しない(今後の課題)
(※コメント内容を受けて改良したので追記の追記の追記まで飛んでください。)
inotify-toolsに依存するので事前に導入しておきます。
logwatch.sh
#!/bin/sh
watchfile=$1
script=$2
if [ $# != 2 ] ; then
echo 'argument is invalid.'
exit
fi
while bookmark=$(awk 'END { print NR+1 }' < "$watchfile") ; \
inotifywait -e MODIFY "$watchfile" >/dev/null 2>&1
do
BKUP_IFS=$IFS
IFS='
'
for line in $(tail -n +"$bookmark" "$watchfile")
do
"$script" "$line"
done
IFS=$BKUP_IFS
done
% echo 'line:1' > hoge
% ./logwatch.sh hoge /bin/echo &
% echo 'line:2' >> hoge
line:2
% echo 'line:3
line:4
line:5' >> hoge
line:3
line:4
line:5
こんなやらんでも便利なツールがあるよーというのがあればぜひご教授ください。
追記
コメントでtail -qF
が使えるよというのを教えていただきました。以下改良版。
logwatch2.sh
#中略
tail -n +$(awk 'END { print NR+1 }' < "$watchfile") -qF "$watchfile" 2>/dev/null | while read -r l ; do "$script" "$l" ; done &
追記の追記
閲覧するだけならtailfやlessのFコマンドも使えそうです。
追記の追記の追記
% tailf -0 | grep "pattern" | some_command
でいい気がしてきた。