• 締切済み

シェルの変数の動作についての質問

solaris8上で、シェルから別のシェルを子プロセスを動作させて その子プロセスが終了したかを判定するシェルを作成しました。 そのシェルの抜粋は下記のようになっています。 ---------------------------------------------------- "コマンド実行" & PID=$! i=0 ERR_FLG=1 echo " PID="$PID >> tmp.txt   ・・・・(1) while [ 1 ] do   if [ `ps -ef | grep $PID | grep -v grep | wc | awk '{print $1}'` -eq 0 ]; then     ERR_FLG=0     break   fi   "終了条件を満たしたかを確認するサブルーチン"   if [ $? -eq 1 ]; then     echo "Time out" >> tmp.txt     break   fi   i=`expr $i + 1 `   sleep 10 done echo `ps -ef | grep $PID | grep -v grep` >> tmp.txt ・・・・(2) ---------------------------------------------------- 殆どの場合問題なく動作しているのですが、 ごく稀に、(1)と(2)で取得した$PIDの値が異なるという現象が起きます。 当然サブルーチン上で、PIDを書換する処理もありません。 どのような状況の時に、現象が起きるかもはっきりしていません。 この現象の回避方法が判る方がおられましたら御教示の程、 宜しくお願いします。

みんなの回答

回答No.3

 このようなケースでは、下記のようにシェル変数で保存で保存するのではなく、ファイルに書き出しファイルで保存して対応して回避したことあります。 ApacheなどでもプロセスIDをファイルに書き出しているので、ファイルに書き出すのが確実な方法ではと思います。 (1)を下記のように修正 echo " PID="$PID >> /tmp/PID_(シェル固有の識別コード) > (1)の出力結果がPID=766 > (2)の出力結果がps -ef | grep 2766 | grep -v grep PID=766が正しいPIDであれば上記の方法で回避できます。 あと・・・「2766」って「2」「766」ということでないですよね? 「2」「766」なら、psのタイミングによっては普段は表示されないプロセスが表示されることがあるので・・・それが原因になるかもしれません。

koruko
質問者

補足

やはり、ファイル出力した方がいいのでしょうか? 10秒周期でループしているので、その度ファイルを読むことになるので、できれば避けたかったのですが・・ それと、個人的にはファイル化することで、避けられると思いますがシェル変数だと上手く行かないのに、ファイル読込だと大丈夫だと 他人に説明がうまく出来ないのがネックになります。 発生する頻度が非常に低い(30回に1回あるかどうか)ので、はっきりしたことは判らないのですが、 2766は今回のシェル及びシェルで終了させるプロセスとは、全く別のプロセスでした。 但し、偶然「2766」になったのか「766」に「2」が追加されたのかは 現段階では判りません。 ※一応、ループ内でも$PIDの値に変化がないか、ログに出力するように変更しましたが、  現象が起こるのがいつになることやら・・

全文を見る
すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

ふと思ったのだが, なぜ ps -ef してるんだろう. 「指定したプロセスID を持つプロセスの情報」が欲しいだけなら, もっと適切にオプションを指定すればいいのに.

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

> PID=$! > i=0 > ERR_FLG=1 > echo " PID="$PID >> tmp.txt   ・・・・(1) ------------- > echo `ps -ef | grep $PID | grep -v grep` >> tmp.txt ・・・・(2) ------------- > ごく稀に、(1)と(2)で取得した$PIDの値が異なるという現象 (1)で取得したPIDを psでgrep した時に「$PIDの値が異なる」??? 何か変です!! 「grep -v grep」で自分自身を除外しているので「(1)と(2)で取得した$PIDの値が異なる」という現象が、どのような結果なのかを明示してもらわないと何ともアドバイスしようがないです。 更に、何故 (1)と(2)でPIDを取得しているのでしょうか? 自分自身のPIDを知るだけなら(1)で十分で「(2)でPIDを取得し、比較することの意味が不明です」

koruko
質問者

補足

"コマンド実行" の部分であるプロセスを終了させる為のシェル(以降終了シェル)を起動しています。 その終了シェルが終了したら、ループを抜けるようになっていますが 永遠に待ち続けることができないので "終了条件を満たしたかを確認するサブルーチン"にて、 一定の時間になったら"Time out"になるようにしています。 本来で、有れば(1),(2)とも不要なログなのですが、 想定内で終了しないことがあったので、 ・終了シェルのプロセスIDが正常に取れているか? (実際は、whileの前に終了シェル名でgrepした結果をtmp.txtへ出力し同一IDになっていることを確認しています) ・本当に終了シェルが終了してないのか を確認するためにログを入れています。 今回の結果ですと、 (1)の出力結果がPID=766 (2)の出力結果がps -ef | grep 2766 | grep -v grep となっていたので ループ内の何処かで$PIDが書き換わったはずなのですが 原因が判らない状態です。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • シェルについて

    以下のような「プロセスをkillするシェル」を作成しています。 そこで質問なのですが、プロセスが死んだら繰り返しを抜ける ようにしたいと考えているのですが、どのようにすれば実現できるのか 分かりません。 どなたかご存知の方がいらっしゃれば教えていただきたいです。 申し訳ありませんが、宜しくお願いいたします。 #!/bin/csh # 変数定義 set cnt = 3 #リトライカウンタ set i = 1 # ループカウンタ #aaaをkill while ( $i <= $cnt ) ps -ef | grep -v grep | grep aaa | \ nawk '{if(match($NF,"aaa") == 1){system("kill " $2);print "kill: " $2}}' ps -ef | grep -v grep | grep aaa| \ nawk '{if(match($NF,"aaa") == 1){system("kill -9 " $2);print "kill: " $2}}' @ i = $i + 1 end

  • シェルの実行履歴

    はじめまして。 会社にてBTSの管理をすることになったのですが、 システムが落ちた際に自動で起動するシェルが動いていない様で困っています。 仕組みとしては checkシェルが1分ごとに動き監視→落ちていると判断すると、restartシェルが動く という感じです。 ですが朝来ると落ちていることがたまにあり、 たぶんどこかのシェルが正しく動いてないんじゃないか?と思っています。 そこでまず、 checkシェルが正しく動いているのか? を調べようと思いシェルの実行履歴とか見れないのかな? と思い探していたのですが、うまく見つからず困っています。 一応checkシェルも記載いたします。 個人的に怪しいなと思っている箇所は、[怪しい] と記載されている辺りです。 これを作成した人が何も情報を残さずにやめてしまって、どういう根拠で条件を設定しているのか不明なんです。 ---------------------------------------------- #!/bin/sh tomcat_home=/usr/local/scarab-1.0-b20/tomcat chk_log=$tomcat_home/logs/catalina.out while true do btspid=`ps ax | grep "\[java\]" | awk '{print $1}'` [怪しい] isAlive=`tail -n 261 $chk_log | grep OutOfMemoryError | wc -l` if [ $isAlive -lt 3 ]; then echo "scarab is still alive, error count = $isAlive : pid = $btspid" else echo "scarab is dead... errot count = $isAlive ; pid = $btspid" ~/restart.sh # break fi sleep 60 done ------------------------------------

  • FEDORA 4 MySQL プロセス 死活監視

    タイトル通り、mysqld のプロセスがなければ、管理者宛にメールを送りたいと考えています。また、シェル又は、PHPをcron(1分間隔)で定期実行もあわせて考えています。 考えたシェル:mysqlch.sh #!/bin/bash mail_body_tmp=/tmp/ps_chk.tmp MAIL_TO=root@localhost rm -f $mail_body_tmp for PROC in $@ do ps -ef | awk {'print $8'} | grep $PROC | grep -v grep | grep -v $0 1>&2>/dev/null if [ ${?} -ne 0 ] ; then echo Process \"$PROC\" Down in $HOSTNAME >> $mail_body_tmp fi done if [ -e $mail_body_tmp ]; then mail -s "Process Down Information. $HOSTNAME" $MAIL_TO < $mail_body_tmp logger -t svchk < $mail_body_tmp fi 実行するときは、mysqlch.sh mysqld しかし、プロセスDOWNでも、メールがきません。 修正する所、またはこの方がいいというアドバイスお願いいたします。

  • シェルの中からシェルを呼び出して判定

    UNIXで以下のようなシェルが動作しております。 #!/bin/sh su abcdef -c './GHI'; err=$? if [! $err -eq 0 ] then echo エラーが発生しました fi exit このシェルは「abcdef」ユーザに移ってカレントディレクトリのシェルコマンド「GHI」の結果を判定するというものです。 UNIX上では問題なく動作しております。 これをLinuxでそのまま動作させると「err」に「su abcdef」というユーザ切替コマンド自身の正否を格納しているようです。 「'」でくくられた範囲内で結果をファイルに格納したりして、その後ファイルの中を見て判断するとうまくいくことは分かっておりますが、出来たらファイルなど使いたくありません。 このような場合、みなさんどうしてるんでしょうか? よく出てくるパタンだと思うのですがどうしても良い対処が見つかりません。 どうか宜しくお願いします。 Linuxは「miracle-Linux2.0」というOSです、いわゆるRedHat系です。

  • シェルスクリプトの変数の制限?

    こんにちは。 シェルスクリプトで謎の現象が起こりまして悩んでいます。 現在、 #!/usr/bin/sh var='foo' if [ $? - eq - 0 ]; then mv xxx.bz2 xxx.old.bz2 echo $var | bzip2 -z >xxx.bz2 fi といった感じのシェルスクリプトを動かしています。 これを手作業で、 foo | bzip2 -z >xxx.tmp.bz2 とやると、xxx.tmp.bz2は1.2MB程度のファイルとなるのですが、 上記のシェルスクリプトで実行すると8KBほどにしかなりません。 シェルスクリプトの変数のサイズの制限かと思い、調べてみましたが、 特に制限があるとの資料はみつかりませんでした。 fooの出力がバイナリなので、そのせいかとも思ったのですが、unix系列の場合、windowsと違ってテキスト/バイナリの区別はないはずだしということで、理由がわかりません。 シェルの変数には、やはり制限があるのでしょうか?それとも他の理由でしょうか。ご存知の方がいらっしゃいましたら、ご教示お願いします。 環境はsolarisです。バージョンは、 $ cat /etc/release Solaris 10 8/07 s10s_u4wos_12b SPARC Copyright 2007 Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms. Assembled 16 August 2007 です。よろしくお願いします。

  • シェルスクリプトの正規表現

    こんばんは。 CentOSでサービスを再起動しようと思ったのですが、資料に書いてある 通りにスクリプトを作っても動きません(起動はできるけど 再起動、停止ができない)。 仕方がないのでプロセスをkillしたあとスクリプトを起動して再起動 する方法を取ろうとしていますが、最後の1歩で詰まりました。 echoでps -axをした結果を変数に入れて先頭の数字(PID)だけを 切り出そうとするのですが、プロセスIDが、空白+PID4桁の時と 空白なしPID5桁のときとあるので上手くHitさせることが出来ません。 mofu=`ps -ax|grep qmail-send` 4桁) mohe=`expr "$mofu" : \(^\s[0-9]*\)'` 5桁) mohe=`expr "$mofu" : \([0-9]*\)'` kill $mohe /etc/rc.d/init.d/qmail シェルスクリプトで自動化したいので、PIDの桁数に関係なく確実に killしたいです。 上手い方法があったら御教授下さい。 よろしくお願いします。

  • シェルスクリプト

    2月14日頃質問のあった”UNIXのシェルスクリプトを使用してテキストファイルのある列にある特定の文字列を条件としてその行を出力するということをやりたい”を下記のように作ってみました。問題ないか逆質問の形で投稿します。(ルール違反かもしれませんが質問が締め切られているので・・・) #!/bin/bash CAT=YAHOO while read LINE do echo $LINE > tmp.txt DOG=`cut -d" " -f2 tmp.txt` if [ "$CAT" = "$DOG" ] then echo "$LINE" fi done < catalog.file

  • awk外で宣言した変数の参照

    kshを使用して、以下のようなシェルを作成しています。 しかしawk内で$iと$iiが参照出来てない様子です。 どのようにすれば参照できますでしょうか。 ■シェルの中身 #/usr/bin/ksh for i in `cat /tmp/hoge |awk -F : '{ print $3 }' | sort | uniq -d` do if [ $i != "" ]; then for ii in `cat /tmp/hoge` do echo $ii |awk -F ":" '{ if ( $3 -eq $i ) print $ii }' done fi done ■エラー awk: 0602-562 フィールド $() が正しくありません。 入力の行番号は 1 です。 ソースの行番号は 1 です。

  • system関数でのシェル起動について

    system関数でシェルコマンドを発行しているC言語のプログラムがあります。 起動されるシェルコマンド(Cシェル)は2重起動防止のため以下の様にコマンド名をgrepしてPIDを取得し、2つ以上あると2重起動と見なしてコマンドを終了させています。 ps -aef | grep 自身のコマンド名 | grep -v grep ~ この時1回目の起動であるのに2重起動チェックに引っかかってしまいコマンドが実行されませんでした。 デバッグしたところ"csh コマンド名"のPIDとは別に一瞬"sh -c コマンド名"というプロセスがあってそれのPIDと合わせて2つに起動していると見なしていました。 調べたところsystem関数はsh経由(sh -c)でコマンドを実行するためだと言う事が分かり納得出来ました。 また元々バックグラウンドで起動させたいコマンドだったので以下の様に"&"を付与したところ2重起動チェックには引っかからなくなりました。 system("コマンド名 &") バックグラウンド起動させても2重起動チェックで弾かれれば納得出来るのですが、通常の起動と何が違うか分からずに釈然としません。 良く分かりませんが、通常起動だとオーバーヘッドで実行に時間がかかりチェックで弾かれるけど、バックグラウンドだと一瞬で起動されてたまたま上手く行った様に見えるだけだったりするなどなのでしょうか?? もしご存知の方がいらっしゃいましたらご教示頂けると幸いです。

  • RedHatでのシェルスクリプトについて

    こんにちは。また質問させて下さい。 redhat7.0のシェルスクリプトで、 サンプルコード片手に以下のコードを記述しました。 やりたい事は、もしaaa.txtというファイルが存在したら その内容を表示させ、存在しなければその旨のメッセージを 表示させる、という単純なものです。 この時、ファイルが存在しない時に ./test.sh: /tmp/aaa.txt: No such file or directry というエラーになってしまいます。 エラーを抜けてメッセージを表示させるには どうしたらいいでしょうか。 アドバイスよろしくお願いいたします。 *********記述したコードです。************* #!/bin/bash fileName=/tmp/aaa.txt read varStr1 varStr2 <fileName if [ -a fileName ]; then echo {$varStr1} else echo{$fileName}{$varStr2} fi

VBAでセル内変更文字列の色付け
このQ&Aのポイント
  • VBAを使って別ブックの一覧を参照し、指定範囲に検索文字列が含まれる場合に文字列の置換、対象セルの色付け、件数の表示を行うコードを変更したいです。
  • 変更した文字列のみ文字色を変更するためのコードを知りたいです。
  • 現在のコードは複数条件で一括置換を行い、置換が行われたセルに赤色を付けて件数を表示するものです。
回答を見る