特定の出力がされるまで処理を繰り返し、出力されたら処理を停止する方法


特定の出力がされるまで処理を繰り返し、出力されたら処理を停止する方法がわからないので、ご教示ください。

例えば、特定の文字列が出力されるまで、pingを繰り返そうとする場合、  
1.ping.txtに文字列"time out"が出力されるまでpingを実行  
2.time out が含まれていれば、再度pingを継続  
3.time out が含まれていないか、試行回数が10回に至れば、"終了"をecho  
と動作させることを仮定しています。

[code]

    #!/bin/bash -v
    ipaddr="10.0.10.101"
    count=10
    ping -c $count $ipaddr > ping.txt
    if echo ping.txt | grep 'time out'
    then
    /繰り返し/
    else
    echo "終了"
    fi
    
[/code]




pingの結果をgrepで判定するのは次の理由で得策ではありません。

  * pingのエラーはタイムアウト以外にもある。(TTL expire、host/network unreachable)
  * タイムアウトの場合に"time out"と表示するとは限らない。OS Xのpingも黙ってるはず。実装によっては日本語で表示する場合もある。

pingはエラーがあった場合0以外の終了コードを返すので、それによって分岐できます。

[code]

    #!/bin/sh 
    ipaddr="10.0.10.101"
    count=10
    loop=10
    for i in `seq $loop` do
        ping -c $count $ipaddr > ping.txt && break
        sleep 5
    done
    
    echo '終了'
    
[/code]

`ping.txt`の用途が単に結果判定用で保存しておく必要が無いなら`ping.txt`の代わりに`/dev/null`にリダイレクトします。




以下は `grep` の `-m` オプションを使うバージョンです。

> grep(1)
[code]

>     -m NUM, --max-count=NUM
>       Stop reading a file after NUM matching lines.
>  
[/code]

※ OSX にデフォルトでインストールされている grep コマンドには `-m` オプションがないかもしれません。

[code]

    #!/bin/bash -v
    ipaddr="10.0.10.101"
    count=10
    msg="timeout"
    
    for ((i=1;i<10;i++))
    do
      if ping -c $count $ipaddr | grep -q -m 1 "$msg"; then
        sleep 5
      else
        break
      fi
    done
    
    echo "終了"
    
[/code]

なお、"timeout" を検索していますが、"timed out" で検索すべきではないでしょうか？

