rsyslogで外部プログラムの実行


よろしくお願いします。

環境:LINUX CentOS 5.3

syslogをrsyslogに変更する事で、ログの吐出時点で外部プログラムを実行することは可能でしょうか?
また、可能であればログの内容を実行プログラムに渡すことは出来ますでしょうか?

実装計画としては、アパッチのアクセスログをシスログ経由で転送し、ログの内容によって登録処理(キューなどへ)をさせたいと思います。
アクセスに対してリアルタイムで登録させたいのでクーロンでの実装は考えておりません。


解説もしくは参考URLをいただければ助かります。


※syslog-ngなどで実装可能であればそちらの情報もいただけると助かります。

回答の条件
  • 1人10回まで
  • 登録:
  • 終了:2011/03/18 00:28:14
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:JULY No.3

回答回数966ベストアンサー獲得回数247

ポイント60pt

アパッチのアクセスログをシスログ経由で転送し、

まず、この点ですが、エラーログに関しては Apache 自体で syslog へ送る事が出来ますが、他のログは、apache 自体がファイルへ書き出してしまいます。

ErrorLog のドキュメント:

core - Apache HTTP サーバ

アクセスログの出力に使われる CustomLog のドキュメント:

mod_log_config - Apache HTTP Server

なので、まず、Apache 自体が吐き出すファイルを syslog へ送るための仕組が必要です。

下記のページでは、短い Perl のスクリプトを用意して、CustomLog の出力先として、このスクリプトを実行させるようにし、スクリプト中で、syslog サーバへ送っています。

http://www.oreillynet.com/pub/a/sysadmin/2006/10/12/httpd-syslog...

また、もっと単純に logger コマンドを呼び出すようにする例もありました。

DSAS開発者の部屋:Apacheのアクセスログをsyslog経由で出力するためのモジュールを作りました

この方は、syslog へ送るためのモジュールを作っているみたいです。


... と、ここまでが前段階(^^;。


ログの内容によって登録処理(キューなどへ)をさせたいと思います。

既に TransFreeBSD さんが回答されているように、syslog-ng で外部プログラムに処理させる方法はありますし、同様の事は rsyslog でも出来ます。

Actions - rsyslog.conf rsyslog

上記ページの「Named Pipes」という節に書かれていて、「|」を使って名前付きパイプを指定し、名前付きパイプに関連付けられたプログラムに処理させる事が出来るようになっています。

名前付きパイプに処理させる方法は、下記のページの angel さんの回答が詳しいです。

syslog.confの設定でinsert,updateだけのログを取りたい

で、上記のページを見ると分かりますが、名前付きパイプを使って外部プログラムに処理挿せる方法は、syslog-ng や rsyslog じゃなくても出来ます。どんな syslog サーバでも出来るかは、ちょっと分かりませんが、古くから Linux で使われている syslog サーバでも、名前付きパイプは対応しています。

Man page of SYSLOG.CONF

なので、実は前述の事は、rsyslog や syslog-ng によらず、多くの syslog サーバで実現可能です。

強いて言うと、先に紹介した rsyslog のマニュアルのページに「Shell Execute」という節があり、「^」で任意のプログラムが実行出来そうです。ただ、その解説文で「WARINING」という警告文があって、あまり推奨出来るものでは無さそうです。しかも、この Shell Execute で呼び出されたプログラムの標準入力に、ログの内容が送られてくるとは書いていないので、zun1188 さんの目的には合わない可能性があります。

id:zun1188

ご回答ありがとうございます。

おかげで実装できる見通しが立ちました。

名前つきパイプを利用しました。

正確なやり方ではないかもしれませんが、一応実装例を書いておきます。


①名前つきパイプを作成

mkfifo /var/log/test_pipo

②ログの吐き出し先を名前つきパイプに指定 rsyslog.conf

*.* /var/log/test_pipo

rsyslog 再起動

③処理させるプログラムを作成 今回はPHPで作ってみました。

$target = '/var/log/test_pipo';

$set = '/var/log/test';

$handle = fopen($target, "r");

for ($i = 1; $i <= 10; $i++) {

if ($handle) {

$buffer = fgets($handle,1024);

if($buffer !== false) {

echo $buffer;

}

}

}

fclose($handle);

④プログラムを起動

すると流れてくるログをエコーさせることが出来ました。

実際に利用する場合はループ処理を無限ループにしてバックグラウンドで走らせることになります。

もちろんエコーの部分はログに対しての処理に変更します。


勘違いしていたのは、ログが吐き出されるたびにプログラムを実行するのではなく、実行されているプログラムが名前つきパイプを通して取得できるということ。(ここは今でも曖昧ですが)


みなさんありがとうございました。

2011/03/16 15:33:22

その他の回答2件)

id:toshiki2131 No.1

回答回数31ベストアンサー獲得回数0

id:zun1188

ご回答ありがとうございます。ですが、今回はソフトウェア製品の購入は考えておりません。

2011/03/15 11:34:28
id:TransFreeBSD No.2

回答回数668ベストアンサー獲得回数268

ポイント30pt

syslog-ngで出来るようです。以下の「監視機能について」にあります。

http://neta.ywcafe.net/000589.html

注意点として、飛んできたログ毎にプロセスを立ち上げるんじゃなくて、一度立ち上げたら同じプロセスで随時渡すようです。なので、標準入力を待って、一行来たら処理する、というのをループさせています。


導入や設定などは以下

http://www.atmarkit.co.jp/fsecurity/rensai/unix_sec09/unix_sec01...

id:zun1188

ご回答ありがとうございます。

>注意点として、飛んできたログ毎にプロセスを立ち上げるんじゃなくて、一度立ち上げたら同じプロセスで随時渡すようです。

そうなんですね。参考になります。

2011/03/15 11:40:07
id:JULY No.3

回答回数966ベストアンサー獲得回数247ここでベストアンサー

ポイント60pt

アパッチのアクセスログをシスログ経由で転送し、

まず、この点ですが、エラーログに関しては Apache 自体で syslog へ送る事が出来ますが、他のログは、apache 自体がファイルへ書き出してしまいます。

ErrorLog のドキュメント:

core - Apache HTTP サーバ

アクセスログの出力に使われる CustomLog のドキュメント:

mod_log_config - Apache HTTP Server

なので、まず、Apache 自体が吐き出すファイルを syslog へ送るための仕組が必要です。

下記のページでは、短い Perl のスクリプトを用意して、CustomLog の出力先として、このスクリプトを実行させるようにし、スクリプト中で、syslog サーバへ送っています。

http://www.oreillynet.com/pub/a/sysadmin/2006/10/12/httpd-syslog...

また、もっと単純に logger コマンドを呼び出すようにする例もありました。

DSAS開発者の部屋:Apacheのアクセスログをsyslog経由で出力するためのモジュールを作りました

この方は、syslog へ送るためのモジュールを作っているみたいです。


... と、ここまでが前段階(^^;。


ログの内容によって登録処理(キューなどへ)をさせたいと思います。

既に TransFreeBSD さんが回答されているように、syslog-ng で外部プログラムに処理させる方法はありますし、同様の事は rsyslog でも出来ます。

Actions - rsyslog.conf rsyslog

上記ページの「Named Pipes」という節に書かれていて、「|」を使って名前付きパイプを指定し、名前付きパイプに関連付けられたプログラムに処理させる事が出来るようになっています。

名前付きパイプに処理させる方法は、下記のページの angel さんの回答が詳しいです。

syslog.confの設定でinsert,updateだけのログを取りたい

で、上記のページを見ると分かりますが、名前付きパイプを使って外部プログラムに処理挿せる方法は、syslog-ng や rsyslog じゃなくても出来ます。どんな syslog サーバでも出来るかは、ちょっと分かりませんが、古くから Linux で使われている syslog サーバでも、名前付きパイプは対応しています。

Man page of SYSLOG.CONF

なので、実は前述の事は、rsyslog や syslog-ng によらず、多くの syslog サーバで実現可能です。

強いて言うと、先に紹介した rsyslog のマニュアルのページに「Shell Execute」という節があり、「^」で任意のプログラムが実行出来そうです。ただ、その解説文で「WARINING」という警告文があって、あまり推奨出来るものでは無さそうです。しかも、この Shell Execute で呼び出されたプログラムの標準入力に、ログの内容が送られてくるとは書いていないので、zun1188 さんの目的には合わない可能性があります。

id:zun1188

ご回答ありがとうございます。

おかげで実装できる見通しが立ちました。

名前つきパイプを利用しました。

正確なやり方ではないかもしれませんが、一応実装例を書いておきます。


①名前つきパイプを作成

mkfifo /var/log/test_pipo

②ログの吐き出し先を名前つきパイプに指定 rsyslog.conf

*.* /var/log/test_pipo

rsyslog 再起動

③処理させるプログラムを作成 今回はPHPで作ってみました。

$target = '/var/log/test_pipo';

$set = '/var/log/test';

$handle = fopen($target, "r");

for ($i = 1; $i <= 10; $i++) {

if ($handle) {

$buffer = fgets($handle,1024);

if($buffer !== false) {

echo $buffer;

}

}

}

fclose($handle);

④プログラムを起動

すると流れてくるログをエコーさせることが出来ました。

実際に利用する場合はループ処理を無限ループにしてバックグラウンドで走らせることになります。

もちろんエコーの部分はログに対しての処理に変更します。


勘違いしていたのは、ログが吐き出されるたびにプログラムを実行するのではなく、実行されているプログラムが名前つきパイプを通して取得できるということ。(ここは今でも曖昧ですが)


みなさんありがとうございました。

2011/03/16 15:33:22
  • id:JULY
    転記ミスだと思うのですが、気になったので念のため。

    >②ログの吐き出し先を名前つきパイプに指定 rsyslog.conf
    >*.* /var/log/test_pipo

    *.* |/var/log/test_pipo と「|」が抜けていると思いますが...
  • id:zun1188
    JULYさん

    コメントありがとうございます。

    実際の記述にもパイプが抜けていました。
    ドキュメントに以下のようにあるように必要なんですね。

    名前付きパイプ
     本バージョンの rsyslogd(8) は名前付きパイプ(FIFO)へのログ出力を
     サポートしています。ファイル名の先頭にパイプ記号(|)を追加することで、
     宛て先として FIFO もしくは名前付きパイプを使用することができます。
     これはデバッグの際に有用なツールとして使用できます。FIFO は rsyslogd(8) が
     起動するより先に mkfifo(1) コマンドを使って作成されている必要がある点に
     注意してください。

    JULYさんが教えてくれたページを http://ricemalt.blog98.fc2.com/blog-category-4.html (米麹の検証日記)が日本訳してくれています。

    名前つきパイプはファイル(スペシャルファイル)という認識からパイプ渡しの必要性がないと判断してつけていませんでしたがやはりつけたほうがよさそうですね。
  • id:JULY
    > 名前つきパイプはファイル(スペシャルファイル)という認識から
    > パイプ渡しの必要性がないと判断してつけていませんでしたが
    > やはりつけたほうがよさそうですね。

    私も、「『|』無しでも、ひょっとしたら動くかな?」とは思ってい
    たんですが、無しでも動いちゃうんですね。

    多分、名前付きパイプで指定していると、、指定したパスに名前付き
    パイプが無かった場合にエラーになって、単にパスだけ書いてあると、
    普通にファイルに吐き出される、という違いはありそうに思います。

    ちゃんと名前付きパイプが用意されている時にどういう違いがあるのか、
    というのは、ちょっと分かりませんが、色々、実験して見ると面白い
    かもしれませんね。例えば、名前付きパイプだけ用意して、読み出す
    プログラムが動いていない場合、とか。

    ま、「|」を付けておく方が無難だと思いますけどね。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません