- ベストアンサー
メッセージから条件分岐
はじめまして、ご質問させてください。 当方、運用屋で開発ではないのですが、必要に迫られ シェルなんぞを作成しています。 メッセージ: ** TEST ** [TEST] END 上記メッセージが発生した際、「*」が含まれているかを まず検索します。 その結果、含まれていなければそのまま終了。 含まれていれば「*」を「\*」へ変換する。 という構文を考えているのですが、いかんせん 知識が足りずお力をお貸しいただきたく思っています。 よろしくお願いいたします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
awkで叩き台を作ってみました。 シェルスクリプトで書き下すとクォート問題がややこしいので とりあえずawkスクリプトだけ独立した形で。 BEGIN { cmd = "/usr/bin/mail" header = "To: anon-user" } /\*\*/ { s = $0 gsub(/\*/, "\\*", s); #print header | cmd #print s | cmd #print "." | cmd #close(cmd) print s # for debug } 標準入力からわたされたレポートを行毎に確認し、 **が含まれていれば /usr/bin/mail コマンドを起動して メールを送ります。 使い方を忘れかけているので、mailコマンドの使い方を 間違っていたらごめんなさい。 検査の条件はもっと厳しくすることももちろん可能ですし、 複数行をメールで送るようにもできます。
その他の回答 (4)
- sakusaker7
- ベストアンサー率62% (800/1280)
> #!/bin/sh > MSG2=$MSG >sed -ne '/$MSG2: \\*\\* error \\*\\*/ { s/\*/\\*/g >p >} >q >' >このような形でよろしいでしょうか。。。 >入力のメッセージの中で「 ** error ** 」があった場合に >「 * 」を「 \* 」へ変換する。 >添削していただけると幸いです。 まず第一に、$MSG2という変数の内容でチェックしたいのなら、シングルクォートで くくってはいけません。 シェルのプロンプトで $ echo '$PATH' と $ echo "$PATH" の違いを確認してください。 ではダブルクォートでくくればいいかというとそう単純には行かなくて、 \の数を倍にしなければなりません。 って私のサンプルもちょっと変ですね。 #プレビューしたのがまずかったか? #!/bin/sh MSG2=$MSG sed -ne "/$MSG2: \\*\\* error \\*\\*/ { s/\\*/\\\\*/g p } q " こうでしょうか。 ファイルに書き出しておいてファイルの内容を変更するというやり方についてですが、 メッセージの量が多いならそれもありだと思います。 ただ問題は、sed などは基本的にファイルの上書きができないということです。 たとえば xxx.dat というファイルが処理対象だとして、 sed -f cmd.sed xxx.dat > xxx.dat のようにはできません。 GNU sed であれば -i オプションを使って sed -f cmd.sed xxx.dat で上書きができますが、AIXだと違いますよねえ。 #Perlなどを使ってもできます 名前を二つ使っていい(入力と出力)ということならこんな心配も要りませんが。 あ、結果をメールで送るというのがありましたね。 じゃあこういうのはどうでしょう #!/bin/sh MSG2=$MSG sed -ne "/$MSG2: \\*\\* error \\*\\*/ { s/\\*/\\\\*/g p } q " > /tmp/$$ if [ -s /tmp/$$ ] then メールを送る処理 fi rm /tmp/$$
補足
ご回答ありがとうございます。 sedの部分についてはテスト機にて実験してみます。 その結果はまたアップさせていただきます。 また、この問題に付随してですが、どうやらすべてのメッセージ に「 ** 」が入っているわけではなく、全体の3割程度ということが わかりました。 そこで、メッセージの中に「 ** 」が含まれていた場合に sedの処理を行う、という事にしたいと考えています。 (もしかしたら一番最初にお教えいただいたスクリプトが それに近いのでしょうか。。。) おそらくifになるのだとは思いますが、まず検査を入れる ことになるのでsedではないですよね。 (awkとかで見る形になるのか。。。) お手数ですがご教授いただけますと幸いです。 よろしくお願いいたします。
- sakusaker7
- ベストアンサー率62% (800/1280)
作ろうとしているシェルスクリプトに対する入力は、スクリプトに対する引数ですか? それとも標準入力等からですか? とりあえず標準入力から来ると仮定して、 #!/bin/sh sed -ne '/message: \\*\\* TEST/ { s/\*/\\*/g p } q ' な感じで(パターンのところはきちんとしてもらうとして)、 見つけ出したいパターンがあれば * → \* と変換して出力、 パターンがなければ何も出力しない。 という動作にはなると思いますがどうでしょう? あー、結果をMTAに食わせないといかんのですか。 どうしましょうかねえ。
補足
ご回答ありがとうございます。 (時間があいてしまい申し訳ありません。) 入力は標準入力からきます。 ご回答いただきました内容をもとに考えました。 「 ** error ** TEST Message 」 という入力があり、これから「*」を検知し 「\*」にする場合は以下のようになりますでしょうか。 #!/bin/sh MSG2=$MSG sed -ne '/$MSG2: \\*\\* error \\*\\*/ { s/\*/\\*/g p } q ' このような形でよろしいでしょうか。。。 入力のメッセージの中で「 ** error ** 」があった場合に 「 * 」を「 \* 」へ変換する。 添削していただけると幸いです。 また、方法論としてメッセージを一度ファイルへ吐き出し、 そのファイルの中身で「 * 」を「 \* 」へ変換する方式の ほうが楽なのでしょうか。。。
- sakusaker7
- ベストアンサー率62% (800/1280)
すみません間があきました。 申し訳ないんですがまだ状況が飲み込めません。 作成するシェルスクリプトを A とします。 Aで見張る監視アプリケーションをXとします。 Xでエラーが起きたときにAから通達するアプリをYとします。 で、 XというのはAの実行に関係なく動きつづけているものですか? そしてメッセージはファイル(ログ)に吐かれると言うことでよいでしょうか? Aは実行されたXが出したファイルの中身を検索して 条件に合致するメッセージがあることを確認し、 含まれていなかった場合 → Aの実行終了 含まれていた場合 Yにメッセージを送る(このとき変換を行う) ということで良いでしょうか? #!/bin/sh err=`sed -n '/message: \\*\\* TEST/{s/\\*/\\\\*/g;p}' $1` if test -n "$err" then echo "detect error!" #echo $err fi というシェルスクリプトで、引数で渡された名前の ファイルをなめていって、該当のメッセージが見つかれば (テストのため検査を甘くしています)、 標準出力にエコーバックします。 見つからなければだまって終了します。 ログファイルを先頭から見るのでその辺気になりますが、 とりあえず叩き台として。 問題があれば随時補足してくださいませ。
補足
ご回答ありがとうございます。 状況の説明不足のままで申し訳ありません。 流れと状況は、 1.監視ツールでログファイル監視 (ここでエラー検知しログの一行を抽出) 2.監視ツールが今回対象のシェルスクリプトをキックします。 そのとき、抽出した一行をシェルスクリプトへ渡します。 (今回対象シェルスクリプトの中でメールを送信する動作をして います。抽出された一行は本文となります。) 3.送信されたメールの本文で、「*」と表示されるべきはずが 文字化けしたり変な出力になったりと不思議な現象に なってしまうため、「*」をあくまで文字として明示したい。 というのが現状です。 よって、シェルスクリプトが上位にあるのではなく、あくまで 監視ツールからすべてが始まり、監視ツールの動きからシェル スクリプトが呼び出されます。 今回変換したいと考えているものは、ファイルではなく 出力された一行を対象としています。 以上が状況説明となりますが、まだ不足点や見当違いな場所が ありましたらご指摘いただきたく思います。 よろしくお願いいたします。
- sakusaker7
- ベストアンサー率62% (800/1280)
確認なんですが、本当に「シェルスクリプト」じゃなくて 「シェル」を作ってるんですか? その他、 ・メッセージが発生するとはどういうことか? 何かプログラムを実行し、エラーが発生したときとか? ・「そのまま終了」って終わるのは何? ・*→\*の変換をしたのをどこかへ出力するのでしょうか? あとできましたら動かしているOSなんかも。
補足
書き込みありがとうございます。 正確に言うとシェルスクリプトです。 また、「メッセージが発生」とは監視アプリケーションで エラーとなった場合にログに出されるものです。 「そのまま終了」とは、質問している部分が終了する という意味です。 全体が終了するという訳ではありません。 「*→\*」への変換は、別の監視アプリケーションへ メッセージを送るときに「*」のままだと文字コード?の 関係上、必要ない文字が含まれたり文字化けしたりという 現象があったため、「*」を文字として出力したい! と考えているからです。 このスクリプトを動作させるOSはAIXです。 よろしくお願いします。
お礼
試行錯誤しながらですがうまくいきそうです。 いろいろとご教授くださりありがとうございました。