Hatena::ブログ(Diary)

(ひ)メモ このページをアンテナに追加 RSSフィード

2009-05-31 (Sun)

mysqlでいちいちshow databasesとか打つのがめんどい→readlineのマクロで解決

MySQLでいちいちshow tables;とか打つのがだるい。\tみたいなalias設定できないのかなぁ

Twitter / ?

おぉ、readlineのマクロを使えばいいのかー

Twitter / ?

なるほ!ってことでちょっと設定してみました。

# ~/.inputrc
$if mysql
"\C-xd": "show databases;"
"\C-xt": "show tables;"
"\C-xu": "select user,host,password from mysql.user order by user,host;"
"\C-xb": "select user,host,db       from mysql.db   order by user,host;"
"\C-xc": "show create table TN\\G"
$endif

$if applicationでmysqlコマンドだけで有効になるように。

pgsqlチックに\tとか\dとかだと、readlineの行編集のbindと被りまくるのでC-xでprefixするような感じで定義してみた。

MySQL 5.6では

MySQL 5.6のmysqlコマンドはreadlineではなくlibeditを使うようになったので、~/.editrcにこのように書けばOKです。

mysql:bind '^U' vi-kill-line-prev
mysql:bind '^W' ed-delete-prev-word

mysql:bind -s "^xd" "show databases;"
mysql:bind -s "^xt" "show tables;"
mysql:bind -s "^xu" "select user,host,password from mysql.user order by user,host;"
mysql:bind -s "^xb" "select user,host,db       from mysql.db   order by user,host;"
mysql:bind -s "^xc" "show create table TN\\\\G"
mysql:bind -s "^xn" "select count(*) from ;"
mysql:bind -s "^xv" "show variables like '%%';"
mysql:bind -s "^xs" "show slave status\\\\G"
mysql:bind -s "^xm" "show master status\\\\G"
mysql:bind -s "^xp" "show full processlist;"
mysql:bind -s "^xa" "show table status like 'TN'\\\\G"

2009-05-26 (Tue)

Nagiosのcheck_snmpで警告レベル(WARNING, CRITICAL)別に通知先を変えたい

やりたいこと

  • 警告レベル (WARNING か CRITICAL) によって、通知先を切り替えたい。
    • WARNING は PC メールと IRC
    • CRITICAL は 携帯メールと PC メールと IRC
  • 外部ホストの監視は NRPE じゃなくて SNMP (check_snmp) を使っている。

通知先の切り替え

なぜか warn と crit で contactgroup を別々にせねばという思い込みがあり、単一のservice定義では実現できなさそうと思ってたんですが、ひとつのcontactgroupに、service_notification_optionsがwのとcのcontactを入れとけば OK ですね。(thanks: @toshiak_netmark)

unknownとcriticalは携帯+PC+IRCに、それ以外はPC+IRCに通知するようなcontact, contactgroup の定義はこんな感じで:

define contact {
  contact_name  scramble-mail-critical
  use           generic-contact
  email         sc-crit@example.com # list for mobile and PC mail
  service_notification_commands  notify-service-by-sc-crit
  service_notification_options   u,c
  host_notification_commands     notify-host-by-sc-crit
}
define contact {
  contact_name  scramble-mail-warning
  use           generic-contact
  email         sc-warn@example.com # list for PC mail
  service_notification_commands  notify-service-by-sc-warn
  service_notification_options   w,r,f,s
  host_notification_commands     notify-host-by-sc-warn
}
define contact {
  contact_name  irc
  use           generic-contact
  email         dummy@example.com
  service_notification_commands  notify-service-by-irc
  host_notification_commands     notify-host-by-irc
}

define contactgroup {
  contactgroup_name  scramble
  members            scramble-mail-critical, scramble-mail-warning, irc
}

あとは、service (かその雛形のdefine service) で、contact_groupsをscrambleと指定する。

define service {
  name                   oreno-service
  use                    generic-service
  ...
  contact_groups         scramble
  ...
}

check_snmp で、文字列マッチで WARNING を返す

check_snmp は、

  • 数値の範囲指定の場合は、WARNINGを返すかCRITICALを返すか制御できる (-w, -c)
  • 文字列の正規表現マッチの場合は、OKかCRITICALしか返せない (-r)

なので、文字列の正規表現マッチで WARNING が返せません。

ひいては、WARNINGとCRITICALで通知先が変えられません。

なので -r(-R) と同じような感じで、正規表現にマッチしたら WARNING を返すオプション -g(-G) を追加しました。

コードは github にあります。

たとえば、

define service {
  use                  critical-service
  hostgroup_name       db
  service_description  3ware RAID
  check_command        check_snmp_v1!-o extOutput.2 -r OK -g VERIFY
}

とすると、対象サーバの extOutput.2 の内容が VERIFY の場合は WARNING、OKの場合は OK、それ以外の場合は CRITICAL となります。

おちぼひろい

先のcontactの設定だと、RECOVERYの通知はWARNINGと同じ通知方法で来てしまいます。本当は、CRITICALなservice障害のRECOVERYはCRITICALと同じ通知方法で、WARNINGのRECOVERYはWARNINGと同じ通知方法でしたいのですが、簡単にできる方法が思いつきませんでした。(service_notification_commandsのメール送信コマンドを、Nagiosからのメッセージに応じて送信先を切り替えるようなスクリプトにすればできそうですが)

自分の場合、CRITICALなのだけ携帯にメールが来るようにしてるので、そのRECOVERYの通知は携帯には来ません。これはちょっといまいちかなーと思ったんですが、WARNINGの通位はIRCにも流していて、mobircで携帯からそのIRCチャンネルにアクセスできるので、まぁいいかーと考えています。どのみち、CRITICALが出たらPCひろげてIRCでやりとりしながら障害対応しますし。

2009-05-21 (Thu)

NagiosからのアラートをIRCにも通知してみた

Nagiosのアラート通知をメールだけじゃなくてIRCにも通知したいなぁと思ったのでやってみました。

IRC bot

今までだと Plagger 付属の plagger-ircbot を走らせて、適宜 POE の IKC で通知命令を送っていたんですが、ちょっと CPAN を探してみたら、

というのがありました。

karmaもつけられていいなーと思ってこれを使おうと思ったんですが、POE を使っているものの IKC で連携する機能がありません。

そこでこのモジュールを継承して、Bot::IKCBot::Pluggable というのを作りました。

BasicBotとの違いはこんなところです。

  • IKC を使った外部プロセスとの通信機能を実装。
  • privmsg に加えて notice な発言もできるようにした。
  • ボットのする返信発言は notice を使うようにした。

継承しているので、Bot::BasicBot::Pluggable::Module::*やStore::*はそのまま流用できます。

examples/ の下にサンプルスクリプトがあるので興味ある方は見てみてください。


あと、NagIRCBot というのを見つけたんですが、C++で書かれていてカスタマイズがめんどくさそうだったんで今回は使いませんでした。

Nagiosの設定

稼働中の Nagios に、こんな感じで設定を追加しました:

ボットに通知指示を送る command の定義
define command {
  command_name  notify-host-by-irc
  command_line  /usr/irori/bin/notify-alert-to-irc.pl '#taihendaaa' "$NOTIFICATIONTYPE$ Host: $HOSTNAME$ Address: $HOSTADDRESS$ State: $HOSTSTATE$" "Date/Time: $SHORTDATETIME$" "- Info: $HOSTOUTPUT$"
}
define command {
  command_name  notify-service-by-irc
  command_line  /usr/irori/bin/notify-alert-to-irc.pl '#taihendaaa' "$NOTIFICATIONTYPE$ Service: $SERVICEDESC$ Host: $HOSTALIAS$ Address: $HOSTADDRESS$ State: $SERVICESTATE$" "Date/Time: $SHORTDATETIME$" "- Additional Info: $SERVICEOUTPUT$"
}
その command を使った contact の定義
define contact {
  contact_name  irc
  use           generic-contact
  email         dummy@example.com
  service_notification_commands  notify-service-by-irc
  host_notification_commands     notify-host-by-irc
}
既存の contactgroup の members にその contact ("irc") を追加

※members に入っている sc-emerg とかいう contact はメールを送るための contact です。

define contactgroup {
  contactgroup_name  sc-emerg
  members            sc-emerg, irc
}
define contactgroup {
  contactgroup_name  sc-warn
  members            sc-warn, irc
}
define contactgroup {
  contactgroup_name  sc-info
  members            sc-info, irc
}

こんな感じに通知されます

f:id:hirose31:20090521204509p:image

でも、アラート通知は来ないにこしたことはないですね^^


あとは Web サーバの 500 エラーとか MySQL の slow ログをもりもり IRC に出すと、IRC厨にはたまりませんね。

2009-05-19 (Tue)

最近読んだ本

順番とか水平線は、全然なんの関係もこれっぽっちもありません。

聖☆おにいさん(1) (モーニング KC)

聖☆おにいさん(1) (モーニング KC)

聖☆おにいさん (2) (モーニングKC)

聖☆おにいさん (2) (モーニングKC)

聖☆おにいさん(3) (モーニング KC)

聖☆おにいさん(3) (モーニング KC)

デザインのデザイン

デザインのデザイン

デザインの生態学―新しいデザインの教科書

デザインの生態学―新しいデザインの教科書

17歳のための世界と日本の見方―セイゴオ先生の人間文化講義

17歳のための世界と日本の見方―セイゴオ先生の人間文化講義

ポジショニング戦略[新版]

ポジショニング戦略[新版]


儲かるオフィス

儲かるオフィス

gitのブランチ名をプロンプトに表示すると結構便利

gitの配布物に含まれる contrib/completion/git-completion.bash を . すると、gitのサブコマンドやそれに応じたオプション、加えて~/.gitconfigで自分用にaliasしたサブコマンドまで補完してくれるようになり、小学生もにっこりです。

同じく git-completion.bash の中で定義されてる関数 __git_ps1 を使ってシェルプロンプト($PS1)を設定すると、

#...
  if [ -r "$HOME/.bash_completion.d/git" ]; then # = git-completion.bash
    # boldにするエスケープシーケンスは省略してます
    PS1="${PS1}[\$(__git_ps1 \"%s)\")\w]\\$ "
  else
    PS1="${PS1}[\w]\\$ "
  fi
#...

こんなふうにgitのブランチ名を表示してくれます。

f:id:hirose31:20090519011043p:image


git使い始めるとブランチを行ったり来たりすることになると思うんですが、プロンプトに表示しておけば、いちいちgit branch打鍵して確認する手間が省けるのでかなり便利です。gitの作業ディレクトリ以外の場合は__git_ps1の部分は空文字になるので邪魔にもなりません。

2009-05-18 (Mon)

あるあるおハマり大事典 - Nagiosのcheck_tcpのエスケープ

memcachedの死活監視をするのに、同梱の check_tcp を使って、

./check_tcp -H mc101 -p 11211 -E -s "version\r\n" -q "quit" -e VERSION

なんてやろうと思い、

define service {
  use                  critical-service
  hostgroup_name       memcached-servers
  service_description  memcached version
  check_command        check_tcp!11211!-E -s 'version\r\n' -q "quit" -e VERSION
}

とかいう serivce を定義するも、「Socket timeout after 10 seconds」といわれて一向に成功しない。


ちゃんと-Eしてんのになんで\r\nが効かないのー

ムキーー!!


で、結局これで OK でした。

define service {
  use                  critical-service
  hostgroup_name       memcached-servers
  service_description  memcached version
  check_command        check_tcp!11211!-E -s 'version\\r\\n' -q "quit" -e VERSION
}

ちゃんちゃん。

2009-05-15 (Fri)

『[24時間365日] サーバ/インフラを支える技術』の韓国語版が出ました\(^o^)/

韓国語版の『[24時間365日] サーバ/インフラを支える技術』の見本誌が届きました!



f:id:hirose31:20090514233147j:image:w360:right

これが表紙です。日本語版とはだいぶ雰囲気違いますねー

"Hatena"、"KLab/DSAS"がでーんとありますが、それより"VLAN"のほうがどーんとしてますね!


f:id:hirose31:20090514233149j:image:w360:right

今回、「韓国語版に寄せて」という内容の序文をぼくが書き下ろしました。ふむふむ。


f:id:hirose31:20090514233148j:image:w360:right

これが本文です。ふむふむふむー



というわけで、内容はイチミリもわかりませんが、自分たちの書いた日本語原書の書籍がほかの国の言葉に翻訳されるなんて文字通り夢にも思っていなかったので、翻訳の話を聞いたときにはびっくりし、そしてこうやって実物を手にしてみた今、ちょっと感激しています。

まったく韓国語はわからないので、韓国の方々にどのような評判で受け入れられているかわかりませんが、少しでも韓国のエンジニアの役に立ってればいいなーと思っています。


それから本家日本語版も今度6刷が出ることが決まりました。

執筆中はウニーって泣きそうになりながら書いていた時期もありましたが、みなさんのおかげで6刷まで出せたり、ひいては翻訳もされたりと、あぁ書いてよかったなーと今では思っています。本当にありがとうございました!

これからもどんどん刷るゼ!!!

2009-05-12 (Tue)

コンテキストによって返す値を変える関数 - use Want 編が微妙な件

HASHかどうかの判別がなんかへんなのに気がついた。

mainでの判別は問題ないんだけど、ほかのpackageのメッソッド内の map の中だと HASH かどうかの判別ができない。下のコードでは自packageだけど、ほかのクラスの中でkureを読んだ場合も同じように map の中だと HASH かどうかの判別ができない。

なんでだろうーなんでだろうー

WantはPL_op*を覗いてるようでちょっと黒魔法的ですね!


#!/usr/bin/env perl
use strict;
use warnings;
use Perl6::Say;
use IO::File;
STDOUT->autoflush(1);
STDERR->autoflush(1);

MAIN: {
    my $oc = OrenoClass->new(nanka => { sushi => 'hattori' });

    say "* main";
    my $s =    $oc->kure;      # => SCALAR RVALUE
    my %h = %{ $oc->kure };    # => SCALAR REF HASH RVALUE
    map {
        my $s =    $_->kure;   # => SCALAR RVALUE
        my %h = %{ $_->kure }; # => SCALAR REF HASH RVALUE
    } ($oc);
    say "* mainnokurekure";
    mainnokure($oc);

    $oc->kurekure;

    exit;
}

sub mainnokure {
    my $s =    $_[0]->kure;      # => SCALAR RVALUE
    my %h = %{ $_[0]->kure };    # => SCALAR REF HASH RVALUE
    map {
        my $s =    $_->kure;   # => SCALAR RVALUE
        my %h = %{ $_->kure }; # => SCALAR REF HASH RVALUE
    } @_;
}


package OrenoClass;
use Perl6::Say;
use Want;

sub new {
    my($class, %args) = @_;
    return bless {%args}, $class;
}

sub kurekure {
    my($self) = @_;
    say "* kurekure";
    {
        my $s =    $self->kure;   # => SCALAR RVALUE
        my %h = %{ $self->kure }; # => SCALAR REF HASH RVALUE
    }
    map {
        my $s =    $_->kure;      # => SCALAR RVALUE
        my %h = %{ $_->kure };    # => SCALAR RVALUE !!!
    } ($self);
}

sub kure {
    my($self) = @_;

    my @ctx;
    for my $c (qw(
                       VOID
                       SCALAR
                         REF
                           REFSCALAR
                           CODE
                           HASH
                           ARRAY
                           GLOB
                           OBJECT
                         BOOL
                       LIST
                       LVALUE
                       RVALUE
                  )) {
        if (want($c)) {
            push @ctx, $c;
        }
    }
    warn join(" ", @ctx)."\n";

    if (want('HASH')) {
        return +{ %{$self->{nanka}} };
    } else {
        return $self->{nanka}
    }
}

2009-05-11 (Mon)

コンテキストによって返す値を変える関数 - use Want 編

リストコンテキストかどうかは組み込み関数の wantarray で調べられますが、コンテキストによってスカラ(文字列)を返したり、ハッシュのリファレンスを返すには use Want すればいいと教えてもらったのでメモ。

my $server = OrenoServer->new(...);

# want scalar
say $server->archetyp;
say "this server is ", $server->archetyp eq "core" ? "" : "not ", "core";
my $h = $server->archetyp;
print Dumper $h;

# want hash ref
say "this server is ", $server->archetyp->{mysql}  ? "" : "not ", "mysql";
my %h = %{ $server->archetyp };
print Dumper \%h;

exit;

package OrenoServer;
use Want;

# ...

sub archetyp {
    # ...

    my $at = [ core => "co1", webapp => "ap103" ]; # test data
    push @$at, (q4m => "qu101");

    if (want(qw(HASH))) {
        return {@$at};
    } else {
        return $at->[0];
    }
}

2009-05-08 (Fri)

Log::Dispatch::*で色をつけたりつけなかったりファイルに出してみたり

Yappoさんが作ってくれた Log::Dispatch::Screen::Color

を使って、

  • 環境変数 ORENO_LOG の値が:
    • "-"
      • → 色をつけないで、STDOUT に出力
      • daemontools配下+multilogでログるときとか
    • "-" 以外の何か
      • → 色をつけないで、環境変数 ORENO_LOG をファイル名としたファイルに出力
      • 普通にファイルにログりたいときとか
    • からっぽ
      • → 色をつけて、STDOUT に出力
      • デバッグ中とかで端末で起動して目視するときとか

するコード片を書いてみました。

#!/usr/bin/env perl

use strict;
use warnings;

use Log::Dispatch;
use UNIVERSAL::require;

my $logger = Log::Dispatch->new(
    callbacks => sub { my %p = @_; $p{message}."\n" },
   );

my %log_prop = (
    name      => 'oreno_log',
    min_level => 'debug',
);
my $log_class = 'Log::Dispatch::';

if ($ENV{ORENO_LOG}) {
    if ($ENV{ORENO_LOG} eq '-') {
        $log_class .= 'Screen';
    } else {
        $log_class .= 'File';
        %log_prop = (
            %log_prop,
            filename    => $ENV{ORENO_LOG},
            mode        => 'append',
            permissions => 0640,
           );
    }
} else {
    $log_class .= 'Screen::Color';
}

$log_class->require;
if ($log_class =~ /Screen::Color/) { # as you like
    no warnings 'once';
    $Log::Dispatch::Screen::Color::DEFAULT_COLOR->{debug} = { text => 'red' };
}
$logger->add( $log_class->new(%log_prop) );


$logger->log(level=>'info', message => "info message");
$logger->debug("debug me!");

2009-05-02 (Sat)

WEB+DB PRESS Vol.49の・・・

読者プレゼントに当選してました・・・

f:id:hirose31:20090502002418j:image



早速着てみました!!!

f:id:hirose31:20090502002539j:image

ザ・ストリッパーズ!! \(^o^)/

2009-05-01 (Fri)

mtime的に新しいのN個を除いて、パターンにマッチするファイル/ディレクトリパスを返すシェル関数

バックアップスクリプトの中で使って、古いバックアップを消したりするのにいいんじゃないかと思います。

#!/bin/bash

# ... バックアップる ...

# 7 個残して古いディレクトリは消す
for i in $(leave_n_dirs 7 '/var/backup/db/2???????'); do # y3k problem
  cmd="rm -fr \"$i\""
  if [ -z "$DRYRUN" ]; then
    $cmd
  else
    echo $cmd
  fi
done

exit

headの-nに負の数を指定してるので、古いcoreutilsだと動かないかもです。

2003 | 11 | 12 |
2004 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 | 11 | 12 |
2005 | 01 | 02 | 03 | 05 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 12 |
2012 | 01 | 02 | 03 | 06 | 08 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 10 |
2015 | 01 | 02 | 07 | 10 |
2016 | 01 | 05 | 10 | 12 |
2017 | 07 |
2018 | 05 |