如何在Linux中ping通,直到知道主机?


46

如何查验某个地址,找到后就停止查验。

我想在bash脚本中使用它,所以当主机启动时,脚本会不断ping通,并且从主机可用的那一刻起,脚本便会继续...

Answers:


84

Martynas的答案进一步简化:

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

注意ping本身用作循环测试;一旦成功,循环就会结束。循环体为空,使用空命令“ :”来防止语法错误。

更新:我想到了一种使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"

这有点circuit回,但是如果您希望循环可取消,则可以解决问题。


6
要添加“睡眠”(例如,每5秒):while!ping -c1 www.google.com&> / dev / null; 睡5 完成
lepe 2015年

4
默认情况下,ping将等待10秒钟,然后再放弃ping。如果要将其减少到1秒,可以使用-w1
杰克·奥康纳

2
@ JackO'Connor使用BSD ping,这是一个首都-W1
Luke Exton

我唯一的问题是它不能很好地处理SIGINT。如果由于某种原因它永远不会连接,则无法从命令行停止它。
卢克·埃克斯顿

@LukeExton这是由于bash和ping处理SIGINT的方式以及它们如何交互(请参阅此问题)。我没有很好的解决方案,但是有一个缺点:使用Control-Z停止脚本,然后kill %1将其杀死。
戈登·戴维森

25

您可以进行循环,发送一次ping,然后根据状态中断循环,例如(bash):

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

将其放置在脚本中的某个位置将阻止,直到www.google.com可以ping通为止。


2
while truebreak是清晰的解决方案,海事组织。
丹·卡利

1
@DanCarley我将不同意您的意见,因为在公认的答案中,null命令版本可以代替sleep / wait来让您的CPU休息,在这种情况下,我将其称为更清洁的解决方案。这个答案的另一个问题是,它要求读者/用户了解&&的工作方式,以及如果第一个命令失败了,它将不会被调用。这只是一个意见,就像您自己的一样。
哈米德2015年

1
我看到的此解决方案与接受的解决方案之间的主要区别是,此解决方案将回显错误消息“未知主机...”,直到找到为止。要增加睡眠时间(例如每5秒一次):while true; do sleep 5; ping ...
lepe 2015年

20

我知道这个问题很旧...特别是关于的问题ping,但我想分享我的解决方案。

在重新引导主机时,我会用它来知道何时可以再次通过SSH重新登录它们。(因为ping它将在sshd启动前响应几秒钟。)

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

2
这正是我搜索的内容,谢谢!您甚至可以使用CTRL + C中断调用,而该线程中的其他一些解决方案则不是这种情况。
亚历克斯(Alex)

1
请注意,这适用于netcat的BSD版本。Linux发行版中的nmap.org版本以不同的方式实现,因此-z选项不存在,并且-w选项等待连接但成功后不会关闭。但是,在OSX中效果很好。
保罗

这就是为什么您不停止第一个(好的)答案的原因。这是真正问题的答案。
狮子座

11

对目标主机执行一次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

您可以删除sleep 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

上述任何循环也可以与fping一起使用,而不是与ping相比更适合ping,而IMO更适合在脚本中使用。有关详细信息,请参见fping(1)

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

在对机器进行某些操作之前测试机器是否已启动也很有用。一个简单的例子:

在HOST1 HOST2 HOST3中为h; 做
  如果fping -q $ h; 然后
     echo -n“ $ h:”
     ssh $ h“ uname -a”
  科幻
做完了

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

戈登·戴维森答案的进一步增强:

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

使用周围的“ $()”启动一个子shell,因此,如果主机不可用,则可以使用Control-C终止循环。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.