ホストが認識されるまでLinuxでpingを実行する方法は?


46

特定のアドレスにpingを送信し、見つかったらpingを停止する方法を教えてください。

私はそれをbashスクリプトで使用したいので、ホストが起動しているときにスクリプトはpingを続け、ホストが利用可能になった瞬間からスクリプトが続行します...

回答:


84

マルティナスの答えをさらに簡素化:

until ping -c1 www.google.com >/dev/null 2>&1; do :; done

ping自体がループテストとして使用されることに注意してください。成功するとすぐにループが終了します。ループの本文は空で:、構文エラーを防ぐためにnullコマンド " "が使用されています。

更新:Control-Cがpingループをきれいに終了する方法を考えました。これにより、ループがバックグラウンドで実行され、割り込み(Control-C)シグナルがトラップされ、発生した場合にバックグラウンドループが強制終了されます。

ping_cancelled=false    # Keep track of whether the loop was cancelled, or succeeded
until ping -c1 "$1" >/dev/null 2>&1; do :; done &    # The "&" backgrounds it
trap "kill $!; ping_cancelled=true" SIGINT
wait $!          # Wait for the loop to exit, one way or another
trap - SIGINT    # Remove the trap, now we're done with it
echo "Done pinging, cancelled=$ping_cancelled"

少し遠回りですが、ループをキャンセルできるようにしたい場合は、トリックを行う必要があります。


6
「スリープ」を追加するには(5秒ごとなど):while!ping -c1 www.google.com&> / dev / null; 寝る5; 完了
-lepe

4
デフォルトでpingは、pingをあきらめる前に10秒待機します。これを1秒に減らしたい場合は、を使用できます-w1
ジャックオコナー

2
@ JackO'Connor BSD pingを使用して、これは首都です-W1
ルークエクストン

この答えの唯一の問題は、SIGINTをうまく処理できないことです。何らかの理由で接続できない場合は、コマンドラインからこれを停止することはできません。
ルークエクストン

@LukeExtonこれは、bashとpingがSIGINTを処理する方法と、それらがどのように相互作用するかによるものです(この質問を参照)。あまり良い解決策はありませんが、大きな問題があります。Control-Zを使用してスクリプトを停止し、次にそれkill %1を強制終了します。
ゴードンデイヴィソン

25

ループを実行し、1つのpingを送信し、ステータスに応じてループを中断できます。たとえば、(bash):

while true; do ping -c1 www.google.com > /dev/null && break; done

これをスクリプトのどこかに置くと、www.google.comping可能になるまでブロックされます。


2
これwhile truebreakIMO、クリーンなソリューションです。
ダンキャリー

1
@DanCarley受け入れられた答えであるnullコマンドバージョンでは、CPUに休憩を与えるためにスリープ/待機を置き換えることができるという理由であなたに同意しません。その場合、私はそれをよりクリーンなソリューションと呼びます。この回答のも​​う1つの問題は、リーダーとユーザーが&&がどのように機能するかを理解する必要があり、最初のコマンドが失敗した場合に呼び出されないことです。これはあなた自身のように、単なる意見です。
ハミド

1
この解決策と受け入れられた解決策の主な違いは、これが見つかるまで「unknown host ...」というエラーメッセージをエコーすることです。スリープを追加するには(たとえば、5秒ごと):while true; do sleep 5; ping ...
lepe

20

私は質問が古いことを知っています...そして、特にに関して尋ねますがping、私は私の解決策を共有したかったです。

ホストを再起動するときにこれを使用して、再びSSHでホストに戻ることができるかどうかを確認します。(開始さpingれる前に数秒間応答しsshdます。)

until nc -vzw 2 $host 22; do sleep 2; done

2
それがまさに私が探していたものです、ありがとう!CTRL + Cで呼び出しを中断することもできますが、これはこのスレッドの他のソリューションには当てはまりません。
アレックス14年

1
これは、BSDバージョンのnetcatで機能することに注意してください。Linuxディストリビューションのnmap.orgバージョンは異なる方法で実装されているため、-zオプションは存在せず、-wオプションは接続を待機しますが、成功しても閉じません。ただし、OSXでうまく機能します。
ポール

これが、最初の(細かい)答えで停止しない理由です。これが本当の問題の答えです。
レオ

11

ターゲットホストに1回pingを実行します。pingが成功したかどうかを確認します(pingの戻り値はゼロです)。ホストが稼働していない場合は、再度pingを実行します。

次のコードは、ファイルとして保存してホスト名を引数として呼び出したり、最初と最後の行を取り除いて既存のスクリプト内の関数として使用したりできます(waitForHostホスト名)。

pingが応答しない場合、コードは失敗の原因を評価しないため、ホストが存在しない場合は永久にループします。私のBSDマンページには各戻り値の意味がリストされていますが、Linuxのものはそうではないので、これは移植性がないかもしれないと思います。

#!/bin/bash

PING=`which ping`

function waitForHost
{
    if [ -n "$1" ]; 
    then
        waitForHost1 $1;
    else
        echo "waitForHost: Hostname argument expected"
    fi
}

function waitForHost1
{
    reachable=0;
    while [ $reachable -eq 0 ];
    do
    $PING -q -c 1 $1
    if [ "$?" -eq 0 ];
    then
        reachable=1
    fi
    done
    sleep 5
}
waitForHost $1

9
UNREACHEABLE=1;
while [ $UNREACHEABLE -ne "0" ]; 
   do ping -q -c 1 HOST &> /dev/null; UNREACHEABLE=$?; sleep 1;
done

スリープ1を削除できます。これは、ホストは到達可能だが、pingがコード0で終了しない場合のフラッディング問題を防ぐためだけです。


4

stackoverflowで適切なオプションを参照してください。bashのサンプルを次に示します。成功したping結果が返されるまで、次のコードをループする必要があります。


ping -c 1 -t 1 192.168.1.1;
if [ $? -eq 0 ]; then
    echo "192.168.1.1 is up";
else 
    echo "ip is down";
fi


3

上記のループはいずれも、pingではなくfpingで使用できます。IMOは、ping自体よりもスクリプトでの使用に適しています。詳細については、fping(1)を参照してください。

while ! fping -q $HOSTNAMES ; do :; done

また、マシンで何かを行う前にマシンが稼働しているかどうかをテストするのにも役立ちます。簡単な例:

HOST1 HOST2 HOST3のh 行う
  fping -q $ hの場合 それから
     echo -n "$ h:"
     ssh $ h "uname -a"
  fi
やった

1

これは、指定された回数試行します。

t=4; c=0; r=0; until ping -c 1 hostname.com >/dev/null 2>&1 || ((++c >= t)); do r=$?; done; echo $r

エコーする代わりに$r、それをテストし、その値に従って動作することができます:

if ((r)); then echo 'Failed to contact host'; else echo 'Continuing with script'; fi

1

BSD pingでSIGINTを適切に処理するため。

HOST=google.com NO=1; while [ $NO -ne 0 ]; do ping -W1 -c1 $HOST &>/dev/null; NO=$?;echo "$(date) ($HOST) $NO" ; done; echo "$(date) ($HOST) reachable"

機能として

ping_until(){
  local NO=1
  while [ $NO -ne 0 ]; do
    ping -W1 -c1 $1 &>/dev/null; NO=$?
    # Optionally block ICMP flooding
    # sleep 1
    echo "$(date) ($1) ($NO)"
  done
}

0

私は次の機能を使用しています。しばらくしてから試すのをやめるように指示できるので気に入っています。

#!/usr/bin/env bash

function networkup {
  # Initialize number of attempts
  reachable=$1
  while [ $reachable -ne 0 ]; do
    # Ping supplied host
    ping -q -c 1 -W 1 "$2" > /dev/null 2>&1
    # Check return code
    if [ $? -eq 0 ]; then
      # Success, we can exit with the right return code
      echo 0
      return
    fi
    # Network down, decrement counter and try again
    let reachable-=1
    # Sleep for one second
    sleep 1
  done
  # Network down, number of attempts exhausted, quiting
  echo 1
}

このように使用して何かを起動できます:

# Start-up a web browser, if network is up
if [ $(networkup 60 www.google.com) -eq 0 ]; then
  firefox &
fi

0

一般に、データベースまたは他のサーバーが起動するのを待ちたいのですが、あまり長く待ちたくありません。次のコードは10秒間待機してから、サーバーが制限時間内に表示されなかった場合に終了コードを設定します。

サーバーが制限時間の前に表示される場合、次のコードが実行できるようにループが短絡されます。

for i in `seq 1 10`; do date ; sleep 1 ; ping -c1 ${HOST} &>/dev/null && break ; done

0

Gordon Davissonの答えのさらなる強化:

until $(ping -c1 www.google.com &>/dev/null); do :; done

周囲の '$()'でサブシェルが開始されるため、ホストが使用できなくなった場合にControl-Cを使用してループを終了できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.