/dev/null

(◞‸◟)

fabricでリモートホストのログファイルをtailするスクリプトを書くTips

fabricでリモートホストのログファイルをtailするスクリプトを書くという事があります。

多分安直に書くとこんな感じ

from fabric.api import sudo,env

env.hosts=['ap1','ap2','ap3']
env.password="hogehogepiyopiyo"

def tailall():
      sudo("tail -f  /var/log/httpd/access_log")

ap1とap2とap3のapacheアクセスログをtailします。 実行はこう

fab tailall

が、このスクリプトではおそらく期待する要件を満たすことは出来ません。 1つずつ解決していきます。

ホストに対して並列に実行してくれない

このままでは、ap1へtail→Ctrl+C→ap2へtail→Ctrl+C→ap3へtail という動作になってしまいます。 複数ホストのログを流し見するために並列にtailしたい場合、起動時にオプション -P--linewiseを足します。

fab -P --linewise taillall

こうすることで並列にtailが実行され、いい感じに流し見出来ます。 @parallel をつけても良いらしいです。

logrotateすると追従出来ない

これはfabricの問題ではなくてtailの問題。 tailf -f ではリモートファイルが切り替わった時に見失ってしまいます。 その場合は tailf もしくは tail -F を使うとlogrotateした際でもそのまま読み込む事ができます。

ctrl+Cで終了した際にリモートホストへtailプロセスが残ってしまう。

これは少し気づき辛い問題です。気づいた時には大量のtailが残ってたり。 上記のスクリプトを単純に実行し、ctrl+cを押して終了した場合、リモートホストにはtailしているプロセスがそのまま残ってしまっています。

[user@ap1 ~]$ ps aux|grep tail
root     31669  0.1  0.0 181928  3280 ?        Ss   19:39   0:00 sudo -S -p sudo password: /bin/bash -l -c tail -f /var/log/httpd/access_log

該当ホストにいってpsとかしてみないと気づかないので発覚した時は大分驚きます。 これを防ぐためには スクリプト内に env.remote_interrupt = Trueを追加します。

from fabric.api import sudo,env

env.remote_interrupt = True 
env.hosts=['ap1','ap2','ap3']
env.password="hogehogepiyopiyo"

def tailall():
      sudo("tail -f  /var/log/httpd/access_log")

これを追加することでCtrl+cしたら、remoteで実行しているコマンドも終了してくれます。

あとは色々キーボード処理などをよしなにキャッチしてあげればそこそこに使い勝手のあるスクリプトが出来上がります。

from fabric.api import sudo,env


env.remote_interrupt = True

env.hosts=['ap1','ap2','ap3']
env.password="hogehogepiyopiyo"


def tailall():
        try:
                sudo("tail -F /var/log/httpd/access_log")
        except  KeyboardInterrupt, e:
                pass
        return

fab -P --linewise tailall