いますぐ実践! Linuxシステム管理

いますぐ実践! Linux システム管理 / Vol.271 / 読者数:2841名

こんばんは、うすだです。

Ubuntu 16.04 LTS と日本語Remix が4月にリリースされました。

今まで 14.04 LTS を使っていましたが、HDD が手狭になってきたこともあり、 HDD を新調して、えいやーで乗り換えてみました。

移行期はたいてい戸惑いますが、お察しの通り、今回も困っています。

いま、一番不都合に感じているのが、インプットメソッドです。

15.10 から Fcitx が標準となりましたが、 日本語入力の際にキーマップを上書きしてくださるため、 自分でよきように xmodmap で設定した内容がその都度消される、 という悲しい状況に陥っています。

仕方がないので、cron で xmodmap を毎分実行してしのいでいます。
(そのうちサービス化して秒単位で実行するかもしれません。)

とはいえ、悪いことばかりではありません。

新しいものに触れることで、 今まで使っていたものを捨てて乗り換えるという機会も得られます。
引っ越しを繰り返すと余計な荷物が減っていくのと似ていますね。

…と、なるべく前向きに考えるようにすることで、今回の移行を、 技術的にも精神的にも乗り切りたいと考えております。

まだまだストレスの種は尽きませんが、今回もはりきってまいりますよ。

今回のお題 - Swatch でログを監視する (レベル:初級)

前回、Apache のアクセスログをクラスタリングしようとして、 特に成果をあげられないまま、終わってしまいました。

Vol.270 - Jubatus でログをクラスタリングしてみる
http://www.usupi.org/sysad/270.html

やはり、物事を学ぶのに近道はありません。基礎から地道に勉強すべきと思います。 「守・破・離」の「守」を端折るなということですね。

というわけで今回は、「Swatch」を使って、正攻法でログを監視し、 即座に警告を通知するものを作ってみたいと思います。

Swatch の概要とインストール

Swatch とは、指定したパターンがログに記録されたとき、 メールで通知したり任意のコマンドを実行したりする、シンプルなツールです。

SWATCH: The Simple WATCHer of Logfiles
http://swatch.sourceforge.net
※ ものすごくシンプルなページです。

CentOS にも Ubuntu にも同名のパッケージがあり、 下記の手順でさくっとインストールできます。

  $ sudo yum install swatch       (RedHat系の場合)
  $ sudo apt-get install swatch   (Debian系の場合)

パッケージのファイル一覧を見ると、 中身は「swatch」コマンドとPerlのモジュールくらいで、 サービスの起動スクリプトなどはありません。

  $ rpm -ql swatch   (Debian系の場合は dpkg -L swatch)
  /usr/bin/swatch
  /usr/share/doc/swatch-3.2.3
  /usr/share/doc/swatch-3.2.3/CHANGES
  ...中略...
  /usr/share/perl5/vendor_perl/Swatch/Actions.pm
  /usr/share/perl5/vendor_perl/Swatch/Threshold.pm
  /usr/share/perl5/vendor_perl/Swatch/Throttle.pm
  ...後略...

swatchコマンド自体がPerlスクリプトであり、 Swatchのモジュールを使用して自分でPerlで書いて動かすことも可能です。
が、今回はコマンドを使って監視することに注力したいと思います。

  $ file $(which swatch)
  /usr/bin/swatch: a /usr/bin/perl script text executable
  $ perldoc Swatch::Actions

まずは簡単な使い方から

swatchコマンドの大まかな書式は以下の通りです。
(詳細は、オンラインマニュアル(man swatch)などでご確認ください。)

  swatch -c 設定ファイル -t 監視するログファイル

「-c」オプション(または「--config-file」オプション)で設定ファイルを指定し、 「-t」オプション(または「--tail-args」オプション)で監視対象のログファイルを指定します。

設定ファイルには、以下を記述します。複数記述することも可能です。

  watchfor /正規表現によるパターン/
    アクション
    ...

「watchfor」の後に指定した正規表現にマッチすると、アクションを実行します。 複数指定可能です。主なアクションを以下に示します。

echo [モード]...ログを表示
mail [addresses=アドレス][,subject=題名]...メールを送信
exec コマンド...コマンドを実行

たとえば、以下の設定ファイルを作成します。
(メールアドレスの「@」の前に「\」が必要ですが、 Perlをご存じの貴兄ならご理解いただけると思います。)

watchfor /Invalid user/
  mail addresses=usu\@example.org,subject="[secure] alert from swatch"

RedHat系なら「/var/log/secure」、Debian系なら「/var/log/auth.log」 を指定して以下のように実行します。
(設定ファイルが「swatch_invalid_user.conf」という前提です。あと、 Debian系でadmグループに属している人は、sudo なしで実行できます。)

  $ sudo swatch -c swatch_invalid_user.conf -t /var/log/secure

すると、SSHでログインに失敗したとき、 「Invalid user」という文字がログに含まれていれば、 ログの内容を「addresses」に指定したアドレス(無指定の場合は root) 宛にメールしてくれます。

  Subject: [secure] alert from swatch
  From: root@example.com (root)
  To: usu@example.org

  日時 サーバ sshd[PID]: Invalid user ユーザ名 from IPアドレス

メールの設定なんてしていないよという貴兄は、アクションを「echo」に置き換えると、 swatchを実行している端末にログが出力されます。

また、「exec」でコマンドを実行できます。
以下の場合、「notify-send」コマンドでデスクトップに通知します。

watchfor /authentication failure|incorrect password/
  exec notify-send "swatch: $_"

なお、「$_」はマッチした1行のログ全体、 「$数」は指定した「数」番目の単語に置き換わります。

ignore で無視します

「ignore」でログを無視することもできます。
あるパターンのログを対象としたいけれど、例外がある場合に利用すると便利です。 書式は以下の通りです。

  ignore /正規表現によるパターン/

指定したパターンにマッチした場合、以降の設定を評価しなくなります。

たとえば、以下のような設定ファイルの場合、sshd のログで、 「Fail」か「fail」とあれば赤色、そうでない場合は通常の色で表示します。

watchfor /sshd.*[Ff]ail/
  echo red
watchfor /sshd/
  echo normal

1行目の正規表現(「sshd」と「Fail」または「fail」という文字がある) にマッチすれば、2行目のアクションを実行(赤色で表示)します。
3行目の正規表現(「sshd」という文字がある)にマッチすれば、 4行目のアクションを実行(通常の色で表示)します。

ここに、ignore の設定を追加します。

ignore /listening|restarting/
watchfor /sshd.*[Ff]ail/
  echo red
watchfor /sshd/
  echo normal

この場合、「listening」か「restarting」という文字を含む場合、 sshdのログであったとしても表示されなくなります。

  $ sudo swatch -c swatch_ignore.conf -t /var/log/secure

と実行しておいて、sshd (Debian系なら ssh) サービスを再起動すると、 (先の設定ファイルが「swatch_ignore.conf」という前提です。)

  $ sudo service sshd restart

ログには以下が出力されますが、(sudo のログは割愛)

  日時 サーバ sshd[PID]: Received signal 15; terminating.
  日時 サーバ sshd[PID]: Server listening on 0.0.0.0 port 222.
  日時 サーバ sshd[PID]: Server listening on :: port 222.

swatch が出力するログは以下だけになります。

  日時 サーバ sshd[PID]: Received signal 15; terminating.

threshold で端折ります

watchfor と ignore、アクションを設定ファイルに書けば、 特定のログが書き込まれたとき、即座に何か行わせることができるようになります。

ただ、指定したログが大量に発生すると、 たとえばわんさかメールが来てたいへんなことになってしまいます。

そんなときは、アクションに「threshold」を指定することで、 一定数を越える同様のログを無視できます。threshold の書式は以下の通りです。

  threshold track_by=/キー/,type=タイプ,count=カウント,seconds=秒

「track_by」には、thresholdの対象を区別するためのキーとなる文字列を指定します。 固定の文字列を指定すれば対象は全体になります。「$5」などを指定すれば、 プロセスごとに分けてカウントできます。
「type」には、以下の3つのいずれかを指定できます。
「count」には、閾値として使用されるカウント数を指定します。
「seconds」には、範囲となる時間を秒数で指定します。

limit...secondsの間にcountを越えると、seconds経過まで無視する
threshold...secondsの間にcountに達するまでは無視する
both...secondsの間にcountに達するとアクション、その後secondsの経過まで無視する

たとえば、設定ファイルが以下の場合、

watchfor /sshd.*[Ff]ail/
  echo red
  threshold track_by=/sshd/,type=limit,count=1,seconds=60

sshdのログで [Ff]ail が含まれていれば赤色で表示されます。
が、threshold の設定があるため、最初の1行が表示された後、 60秒間はマッチするログがあっても表示されなくなります。

おわりに

以上、Swatch を使ってログを監視し、 条件にマッチしたログがあったら即座にアクションを起こす方法を、 さらっとご説明しました。

シンプルなようですが、Perlの記述が使えることを利用するなどすれば、 もっといろいろなことができそうに思います。ぜひお試しください。

宿題の答え

前回の宿題は、

  他のログでもクラスタリングをしてみましょう。

でした。

自分でクラスタリングと書いてしまい、可能性を狭めてしまったことや、 16.04 にしたら Jubatus が動かなくなってしまったことで、 軽く途方に暮れております。

…が、嘆いていても仕方がありません。 あくまでもクラスタリングをすることが目的であって、 何か成果を出すとは言っていないことに希望の光を見出すことにして、 淡々と進めていきたいと思います。
(ちなみに、Ubuntu 15.04 のマシンで確認しております。)

以下では、セキュリティに関するログ(CentOSだと「/var/log/secure」、 Ubuntuだと「/var/log/auth.log」)をクラスタリングしてみました。

今回は、sshd のログに限定し、 単純に単語の出現数だけを見てどうなるかをやってみました。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import re
import socket
import jubatus
from jubatus.common import Datum

def line2datum(l):
  datum = Datum()
  cnts = {}
  for n in l.split(' '):
    if len(n) < 4:
      continue
    if re.match('^\d+\.\d+\.\d+\.\d+$', n):
      n = '0.0.0.0'
    else:
      n = n.lower()
    if n in cnts:
      cnts[n] += 1
    else:
      cnts[n] = 1
  for n in cnts:
    datum.add_number(n, cnts[n])
  return datum

def get_result(centers, r):
  i = 0
  for center in centers:
    if center.num_values == r.num_values:
      return i
    i += 1
  return -1

if __name__ == '__main__':
  if len(sys.argv) != 3:
    print >> sys.stderr, "Usage: %s learnlogfile testlogfile" % (sys.argv[0])
    sys.exit(1)

  jclient = jubatus.Clustering('localhost', 9199, 'auth_log')
  #jclient.clear()
  pat = re.compile('^\S+\s+\d+\s+\d+:\d+:\d+\s+\S+\s+sshd\[\d+\]: (.*)$')

  # learn
  with open(sys.argv[1], 'r') as f:
    l = f.readline().rstrip()
    cnt = 0
    while len(l) > 0:
      sd = pat.split(l)
      if len(sd) > 1:
        datum = line2datum(sd[1])
        if datum is not None:
          jclient.push([datum])
      l = f.readline().rstrip()
      cnt += 1

  # get centers
  centers = jclient.get_k_center()
  print '# centers'
  for center in centers:
    print center.num_values

  # test
  print '\n# test'
  with open(sys.argv[2], 'r') as f:
    l = f.readline().rstrip()
    cnt = 0
    while len(l) > 0:
      sd = pat.split(l)
      if len(sd) > 1:
        datum = line2datum(sd[1])
        if datum is not None:
          r = jclient.get_nearest_center(datum)
          print "%d = \"%s\"" % (get_result(centers, r), sd[1])
      l = f.readline().rstrip()
      cnt += 1

やけに長いですが、大まかな流れは前回のスクリプトと同じです。 詳細の説明は割愛しますが、ざっくり言うと、正規表現にマッチしたsshdのログを対象に、 出現した単語の個数をDatumに放り込んで処理しています。
(3文字以下の単語は無視し、IPアドレスは0.0.0.0に置き換えています。)

まず、前回同様、jubaclusteringを実行します。
ただ、今回は k を 5 にして実行したいので、 sed コマンドで 3 を 5 に書き換えた設定ファイルを作成し、 それを引数に指定しています。

  $ . /opt/jubatus/profile
  $ sed -e 's/"k" : 3,/"k" : 5,/' \
    /opt/jubatus/share/jubatus/example/config/clustering/kmeans.json \
    > kmeans5.json
  $ jubaclustering --configpath kmeans5.json

上記のスクリプトを実行すると、以下のような結果が得られました。
(スクリプト名が「clustering_authlog.py」と仮定しています。)

  $ chmod +x clustering_authlog.py
  $ ./clustering_authlog.py /var/log/auth.log /var/log/auth.log
  # centers
  ...中略...

  # test
  1 = "Received SIGHUP; restarting."
  0 = "Server listening on 0.0.0.0 port 22."
  0 = "Server listening on :: port 22."
  ...中略...
  3 = "Accepted password for usuda from IPアドレス port ポート ssh2"
  4 = "pam_unix(sshd:session): session opened for user usu by (uid=0)"
  2 = "Received disconnect from IPアドレス port ポート ...略..."
  2 = "Disconnected from IPアドレス port ポート"
  ...中略...

今回は、「クラスタリングされた番号 = "ログ"」という形式で出力しています。 それっぽい結果が得られた…ように思います。思ってください。

…だから何? という問いが聞こえてくるような気がしますが、 まずは手を動かして実感することが大切なのではないかと思います。(言い訳!)

というわけで、いろいろ試してみてくださいませ。(投げやり!!)

今回の宿題

今回の宿題は、

  Swatchをサービスとして起動してみましょう。

です。

swatchコマンドを刹那的に動かすことが目的ではなく、 365日24時間休みなく我々の代わりに働いていただくことが目的なのではないでしょうか。

ということですので、systemd でも Upstart でも、 レガシーな SysV のinit でも何でも構いませんので、swatch を常時動かしてみましょう。

あとがき

諸般の事情により、Raspberry Pi 3を購入しました。

電源供給が USB なのですが、最低 2A の電流が必要という記載があったため、 iPad 用のアダプタを別途購入しました。

以前購入した初代 Raspberry Pi は、家にある適当なアダプタで動作したのですが、 進化の過程で、よりたくさんの電気が必要になったようです。

で、さあ動かしてみようと思ったら、SDカードを挿す口がありません。
よく見ると、マイクロSDカードの口がありました。

初代はマイクロじゃない大きいSDカードが挿せましたので、先日、 実家で発掘してきた大量のSDカードが使えると思っていたのですが…。
進化の過程で、マイクロな方が選択されたようです。
(8インチや5インチのフロッピーより3.5インチの方が便利だ、 というのと一緒ですね。…はい、例えが古いですね…。)

急遽、近くの電気屋さんで、割高なマイクロSDカードを買ってきました。

という感じで、今、ようやく、 Raspbianが動くところまでたどり着くことができたところです。

冒頭で、新しいものに触れることで、古いものを捨てて乗り換えられると書きましたが、 今回、新しい Raspi だけでなく、アダプタとマイクロSDカードが新たに加わり、 単調にものが増加していっております。

物理的にも古いものを捨てればよい、ということは理解しているのです。
が、人間は感情で動きます。断捨離とかできない性格なのです。

家の収納スペースも、HDD と同様、年々容量が増えればいいのになあ、 と思っている今日このごろです。

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、7月3日(日) の未明に発行したいと思います! (未だ曖昧!!)

 

「いますぐ実践! Linux システム管理」はこちらです。
メルマガの解除、バックナンバーなども、以下からどうぞ。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

その他、作者に関するページは、概ね以下にございます。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://twitter.com/kuriking/ (twitter)
http://facebook.com/kuriking3 (facebook)
https://jp.pinterest.com/kuriking/ (pinterest)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本