6417


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

例えば、特定の文字列が出力されるまで、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]


CC BY-SA 3.0
2015-02-12T17:25:49.570
6407
2015-02-17T22:51:51.377
2015-02-17T22:51:51.377
7590
7590
question
bash
特定の出力がされるまで処理を繰り返し、出力されたら処理を停止する方法


リダイレクトにはバッファがあります。 `ping.txt` には ping
操作でバッファが一定程度貯まった後書き込まれ始めるので、その方法では処理を停止出来ないです。

`-c count` の代わりに、 `while loop` と `＄？` を使うと解決出来ると思います。

[code]

    #!/bin/bash -v
    ipaddr="www.google.com"
    count=10
    rm ping.txt
    
    while [ $count -gt 0 ]; do
            count=$(( $count - 1 ))
            ping -c 1 $ipaddr >> ping.txt
            if [ $? -ne 0 ]; then   # fail -> reset;
                                    # you can also only check error code for timeout according to man page,
                                    #        2       The transmission was successful but no responses were received.
                    count=10
                    sleep 5
            fi
    done
    
    echo "Success"
    
[/code]


CC BY-SA 3.0
2015-02-12T18:35:21.407
6408
2015-02-12T22:11:10.150
2015-02-12T22:11:10.150
4978
8229
6407
answer


以下は `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" で検索すべきではないでしょうか？


CC BY-SA 3.0
2015-02-12T23:43:59.747
6413
2015-02-12T23:43:59.747
6407
answer


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`にリダイレクトします。


CC BY-SA 3.0
2015-02-13T01:07:21.537
6417
2015-02-13T01:07:21.537
5793
6407
answer