Linuxサービスの稼働状況を確認して別処理を動かすシェルスクリプト

このQ&Aのポイント
  • Linux(Red Hat Enterprise Linux5.6)にて、稼動しているサービスの実行結果を参照&判断して別処理を動かすシェルスクリプトを作成したいと考えています。具体的には、nfsとnfslockのサービスの稼働状況を確認し、ランレベル3でどちらかのサービスがoffになっていたらshutdownコマンドを実行する処理を実装しましたが、while文内部の値を外部で使用できないという問題が発生しています。
  • 現在のスクリプトでは、chkconfigコマンドを使用してnfsとnfslockのサービスの稼働状況を取得し、while文で1行ずつ読み込みながら処理を行っています。ただし、while文内で取得したサービスの稼働状況を外部で使用することができず、常にshutdownコマンドが実行されてしまいます。
  • この問題を解決するためには、while文内で取得したサービスの稼働状況を外部の変数に格納する必要があります。具体的には、nfsとnfslockのサービスの稼働状況をwhile文内で確認し、外部の変数に格納しておくことで、後で外部で比較判定を行うことができます。また、if文内での比較演算子の使用方法にも注意が必要です。
回答を見る
  • ベストアンサー

while文内部の値を、外部で使用したい

Linux(Red Hat Enterprise Linux5.6)にて、稼動しているサービスの実行結果を 参照&判断して別処理を動かすシェルスクリプトを作成したいと考えています。 例) 1. nfsのサービス稼働状況を確認 2. nfslockのサービス稼働状況を確認 3. 両サービスにおいて、onかoffの判別(ランレベル3) 4. サービスどちらかがoffになっていたら、shutdown -r now コマンドを実行 #chkconfig --list|grep nfs nfs 0:off 1:off 2:off 3:off 4:off 5:off 6:off nfslock 0:off 1:off 2:off 3:on 4:on 5:on 6:off 上記例3.にて、while文内部の値をwhileの外部で比較しようとしましたが、値に 稼働状況が格納されておらず 両サービスの比較結果に関係なくshutdownコマンドを実行していました。 他人のスクリプトを参考に見よう見まねで作成した為スキル等が不足していると 思いますが、ご指導お願いします。 以下、自分が作成したスクリプトです。 #!/bin/sh chkconfig --list | grep nfs|while read line ; do service=`echo $line|awk ' {print $1}'` echo $service if [ $service = "nfs" ] ; then nfsd=`echo $line|awk ' {print $5}'` fi if [ $service = "nfslock" ] ; then nfsd=`echo $line|awk ' {print $5}'` fi done if test nfsd != "3:on" || test nfslockd != "3:on" ; then shutdown -r now fi

質問者が選んだベストアンサー

  • ベストアンサー
  • notnot
  • ベストアンサー率47% (4846/10257)
回答No.1

直接の原因は、パイプを使うとそれぞれがサブシェルで実行されるため、そこでシェル変数にセットしても、メインプロセスからは参照できません。ファイルを経由するか、 A=`xxx | yyy | zzz` のように出力させて変数にセットして後で調べるか。 で、そもそもchkconfigは現在の稼働状況を調べるコマンドではありません。詳しくは man chkconfig を。 テストしてませんが、 if ! service nfs status >/dev/null || ! service nfslock status then shutdown -r now fi かな。

Hekuchi
質問者

お礼

回答ありがとうございます。 パイプの仕様について、よく知らずに使っていたのが原因ですね。 他の方法を模索してみます。 chkconfigの件もありがとうございます。

その他の回答 (1)

  • notnot
  • ベストアンサー率47% (4846/10257)
回答No.2

No1です。書き漏らし。 動作には影響しませんが、service nfslock status にも >/dev/null をつけた方がいいでしょうね。つけないと毎回cronからメールが来ちゃいます。

関連するQ&A

  • シェルスクリプト shiftとwhile

    下記の内容はスクリプトの一部を抜粋した内容です。 2箇所、理解が出来ない部分があるので、教えて頂けますでしょうか。 ------------------------------------------------ shift $(( $OPTIND -1)) if [ $# -eq 0 ]; then FileName="" elif [ $# -eq 1 ]; then if [ "\-" = "$1" ]; then FileName="" else FileName="$1" fi else echo "オプションが多い" exit fi if [ "" = "$FileName" ]; then while read line; do fcnctionA "$line" done else while read line; do fcnctionA "$line" done < "$FileName" fi ------------------------------------------------ (1) if [ "\-" = "$1" ]; then 部分が理解できないのですが、教えて頂けますでしょうか。 (2)  if [ "" = "$FileName" ]; then while read line; do fcnctionA "$line" done 基本はファイル名を指定して実行する事を前提としていると思います。 ファイル名を指定しないでスクリプトの実行をする場合は、1行ずつ標準入力で 入力すると思うのですが、このような使い方をする場合はあるのでしょうか。 下記よりも便利な点があるようでしたら、教えて頂けますでしょうか。 または、shiftと関係があるのでしょうか? if [ ! "" = "$FileName" ]; then while read line; do fcnctionA "$line" done < "$FileName" fi

  • While 二重ループ処理について

    Bashのシェルスクリプトでwhileを使いループの処理を行いたい。 現状以下のようにファイルAの中に値”1”とイコールの場合に$awkを表示しています。 これを値”1”部分へファイルBの中の値を順にチェックできるようにしたいのです。 while IFS="$LF" read $READ_R record; do IFS='; ' set -- $record for awk in $3; do if [ "$awk" == "1" ]; then for awk in $4; do echo "$awk" done fi done done < "$1" 初心者のため分かり難い質問かもしれませんがよろしくお願いします。

  • 最近、急にSSHやftpが外部から繋がらなくなったんですが・・・

    telnet以外特にアクセス制限をかけていなかったのに 突然、外部のWindowsHOSTからインターネットを通じて 自宅のRedHat8へ接続できなくなりました。 sshとftpです。TeraTermを使用しています。 最近、portmapとnfsとか言うサービスを、 いらないかなぁ~と思い、chkconfigで停止させたのですが、 関係ありますか? あとサーバーをshutdownする時に限り、いつも nfsの個所が、今まで[OK]だったのが、[failed]とかいう 赤文字になるようになったのですが・・・? これも関係ありますか?? nfsとかportmapって何なんでしょうか? HPをいろいろ見ても良く意味がわかりません。 どうかそれも合わせて、アドバイス・ご教示願います。 それでは、よろしくお願いします。

  • 【シェル】whileコマンドについて

    【シェル】whileコマンドについて OS:Solaris10 SH:Bシェル お世話になります。 whileコマンドにてテキストから、先頭に"#"(シャープ)が付いている行と、 空白行以外を読み込ませたいです。 ところが、メイン処理にawkコマンドを入れると、テキストを読む時点で、 行全体ではなく、指定したフィールド内の文字列を読みにいくため、 "#"(シャープ)が付いている行を無視することができません。 ====== while.sh ====== #!/bin/sh while read LINE do echo $LINE | awk '{print $2}' done < list.txt | grep -v "^#" | grep -v "^$" ====================== ------ list.txt ------ 1 2 3 #4 5 6 7 8 9 ---------------------- ****** 出力結果 ****** 2 5 8 ********************** ** 出力させたい結果 ** 2 8 ********************** whileコマンドのオプション等で、テキスト内に特定の記号がある行は 無視して読み込ませる方法がありましたら、ご教授ください。 宜しくお願い致します。

  • duコマンド+アルファで大きなファイルを検索

    以下のコマンドでディスク内の大きなファイルを検索することはできるのですが、ディレクトリも検索されてしまう為、ファイルかどうか判断するのは自分で見なければなりません。 --------------------------------------------------------------- du -a `ls -la /| egrep -wv "backup|^l[rwx-]+|skel|\.|\.\.|^total|proc" | awk '{print $NF}'` | sort -nr | head -30 出力された内容がディレクトリなら偽として、大きなファイルだけをしりたいのです。 一度ファイルに出力してからwhileを使って一行ずつifコマンドでディレクトリなら偽として出力していけばできるのですが。 ------------------------------------------------------------------ while read line ;do if [ -f "$line" ] ; then echo "$line" ; fi ; done < list これと同じ結果をファイルを作成せずにやりたいのです。 while分の最後のdoneにファイルをリダイレクトさせる要領で while read line ;do if [ -f "$line" ] ; then echo "$line" ; fi ; done < `printf "$list\n"` としてもうまくゆきません。 どうしたらファイルを作成せずにディスク内の大きなファイルだけを検索する事ができますでしょうか。

  • 日本語が入った本文をユーザごとにメール送信したい

    1行ごとにユーザの情報が記述された内容を 日本語でユーザごとにメールしたいのです。 file.1の中身 01_hamada 1991/01/01 1st 10 01_hamada@メールアドレス 02_yoshida 1992/02/02 2st 20 02_yoshida@メールアドレス 03_satoshi 1993/03/03 3rd 30 03_satoshi@メールアドレス 04_kinosita 1994/04/04 4th 40 04_kinosita@メールアドレス test.sh スクリプト #!/bin/bash while read line; do DAY=`echo "$line" | awk '{print $2}'` RANK=`echo "$line" | awk '{print $3}'` POINT=`echo "$line" | awk '{print $4}'` ADDRES=`echo "$line" | awk '{print $5}'` mail -s test "$ADDRES" < messagebody.txt done < file.1 messagebody.txtの中身 あなたがテストを受けた日は$DAYです。 順位は$RANKです。 点数は$POINTでした。 OSは Red Hat Enterprise Linux ES release 4 (Nahant Update 4) です。これでは日本語ファイルを絡めたスクリプトを 成立させることはできないのでしょうか このままだと、文字化けして$DAY,$RANK,$POINTが そのまま文字列として送信されてしまうのです。 なにか良い方法はないでしょうか

  • シェルスクリプト:while文のリダイレクトはサブシェルで実行されますか

    日頃Linuxを使用している者です。手元にSolaris環境がなく検証できないためSolaris使いの方にお伺いさせてください。 お聞かせいただきたいことは次の一点です。 Q. Solaris8,9,10 のBourneShellは従来どおり、while文でリダイレクトを使ったときは、サブシェルでまわりますか? 上記質問に至った簡単な経緯を申し上げます。 実は、Linuxの/bin/ash(BourneShell相当)スクリプトで while文でリダイレクトしたところ、ループ内の変数がwhileの外でも参照できました。本来BourneShellの場合、当ケースでのループはサブシェルで回るはずですよね。 最近のGNU BASHを始め、ASHもfor,whileのりダイレクトを使ったループもカレントシェルで動作するということでしょうか? そこで、SolarisのSHはどうなのかと思った次第です。以上宜しくお願いします。 p.s. HP-UX, AIXのSHについても情報があればありがたいです。 参考までに、Linux上の実例を記します。 ■test.ash #!/bin/ash n=0 while read line do i=`expr $i + 1` echo "$i: $line" done < $0 echo "total line= $i" ■実験してみる > ./test.ash 1: #!/bin/ash 2: 3: i=0 4: while read line 5: do 6: i=`expr $i + 1` 7: echo "$i: $line" 8: done < $0 9: echo "total line= $i" total line= 9 ← しっかりインクリメントされた変数見れてるし。最近の仕様?

  • Kシェルでの read line と awk

    お世話になっております。 AIX の 標準 kshell にて下記を実行したいと考えております。 <やりたいこと> recode.txt(逐一別のシェルで内容は変更される) の中身に書かれている文字を参照して、test.txt を読み込んで該当する文字列を読み込みたいと考えています。 test.txt は編集可能なので、誤記入対策の為に、空白/タブ行、先頭空白/タブ、行末空白/タブを無視出来るようにしたいと考えています。 例) recode.txt AAAAA test.txt # ~~コメント~~ # ~~コメント~~ # ~~コメント~~ # ~~コメント~~ <AAAAA> test1 test2 test3 <BBBBB> test10 test11 test12 test13 この場合、結果として、test1、test2、test3を得て、このファイルに対して別のシェルを実行したいと思っております。 recode.txt は read line を使って読み込めるのですが、とりあえずテストとして下記のように test.txt を awk( print $1 で先頭空白、先頭タブが無視されるようでしたので) をつかってみたのですが、上手くいきませんでした。 上手くいかないというよりは、「elif [[ ${jug} == "A" ]]; then」の elif がおかしいと言われ、どうも if ~ の部分がおかしいっぽいのですが……すいません、自分ではどうも原因が分からず困っております。 【test.ksh】 (~省略~) (recode.txt 読み込み処理) jug=X while read line ; do if [[ "`awk '{print $1}' ${line}`" == "#" || "`awk '{print $1}' ${line}`" == "" ]]; then elif [[ ${jug} == "A" ]]; then if [[ `awk '{print $1}' ${line}`" == "<BBBBB>" ]]; then break fi test2.ksh ${line} <エラーチェック> elif [[ ${jug} == "B" ]]; then test3.ksh ${line} <エラーチェック> elif [[ "`awk '{print $1}' ${line}`" == "<AAAAA>" and ${recode} == "AAAAA" ]]; then jug=A elif [[ "`awk '{print $1}' ${line}`" == "<BBBBB>" and ${recode} == "BBBBB" ]]; then jug=B fi done < test.txt (~省略~) $line の扱いが間違っているのか、それとも構文的なところなのか…… orz 本業がSEじゃないのでシェルに詳しくなく申し訳ないのですが、基本的なことと存じますが教えて頂けますと幸いです。 宜しくお願い致します。 ※投稿時に先頭空白が上手く処理されないようで、回避方法が解らず、全て左につめられてしまいまして見難く申し訳ありません。

  • シェルスクリプトでwhileを用いてrshを繰り返し使う場合

    Bシェルスクリプトでリモートシェル(rsh)を使う場合の質問です。 現在、以下のような状態です。 有識者の方、アドバイスをお願いします。 ・Aでは、ループされずhostAの場合のみ処理がされます。 (while文が効いていない) ・Bでは、ループされて問題なくhostA,hostB,hostCが処理されます。 (while文が効いている) なぜなのでしょうか。。。(r系コマンドの特性?) ちなみり、リモート側のサーバには.rhostsが設定してあり 問題なくコマンドが通ることは確認済みです。 スクリプトA---------------------------------------------- #!/bin/sh while read line ; do rsh $line hostname done <<END hostA hostB hostC END スクリプトA---------------------------------------------- スクリプトB---------------------------------------------- #!/bin/sh while read line ; do echo " HOST=$line" done <<END hostA hostB hostC END スクリプトB----------------------------------------------

  • if文の質問です

    初心者です。 よろしくお願いします。 aaaという文字を売ったときにだけtrueを表示したいのですが、うまくいきません。 以下の<結果>のようになってしまいます。 どうしたらうまくいくのか例文を探しても載っていなかったので質問しました。 if [ $1 = "aaa" ] ; then echo true ; else echo false ; fi <結果> $ ./test.txt aaa ./test.txt: line 7: syntax error near unexpected token `fi' ./test.txt: line 7: `fi'