Làm thế nào để ping trong linux cho đến khi máy chủ được biết đến?


46

Làm thế nào tôi có thể ping một địa chỉ nhất định và khi tìm thấy, ngừng ping.

Tôi muốn sử dụng nó trong một tập lệnh bash, vì vậy khi máy chủ khởi động, tập lệnh tiếp tục ping và từ thời điểm máy chủ có sẵn, tập lệnh tiếp tục ...

Câu trả lời:


84

Một đơn giản hóa hơn nữa câu trả lời của Martynas:

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

lưu ý rằng bản thân ping được sử dụng làm bài kiểm tra vòng lặp; Ngay khi nó thành công, vòng lặp kết thúc. Phần thân vòng lặp trống, với lệnh null " :" được sử dụng để ngăn lỗi cú pháp.

Cập nhật: Tôi đã nghĩ ra một cách để làm cho Control-C thoát khỏi vòng ping một cách sạch sẽ. Điều này sẽ chạy vòng lặp trong nền, bẫy tín hiệu ngắt (Control-C) và giết vòng lặp nền nếu xảy ra:

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"

Nó hơi phức tạp, nhưng nếu bạn muốn vòng lặp có thể hủy được thì nên thực hiện thủ thuật.


6
Để thêm 'ngủ' (ví dụ: mỗi 5 giây): while! ping -c1 www.google.com &> / dev / null; ngủ 5; xong
lepe

4
Theo mặc định pingsẽ đợi 10 giây trước khi từ bỏ ping của nó. Nếu bạn muốn giảm xuống còn 1 giây, bạn có thể sử dụng -w1.
Jack O'Connor

2
@ JackO'Connor Sử dụng ping BSD, đây là một thủ đô-W1
Luke Exton

Vấn đề duy nhất của tôi với câu trả lời này là nó không xử lý SIGINT tốt. Bạn không thể ngăn chặn điều này từ dòng lệnh, nếu nó sẽ không bao giờ kết nối vì bất kỳ lý do gì.
Luke Exton

@LukeExton Đó là do cách bash và ping xử lý SIGINT và cách chúng tương tác (xem câu hỏi này ). Tôi không có một giải pháp rất tốt, nhưng có một kluge: sử dụng Control-Z để dừng tập lệnh, sau đó kill %1để giết nó.
Gordon Davisson

25

Bạn có thể thực hiện một vòng lặp, gửi một ping và tùy thuộc vào trạng thái phá vỡ vòng lặp, ví dụ (bash):

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

Đặt cái này ở đâu đó trong tập lệnh của bạn sẽ chặn, cho đến khi www.google.comcó thể ping được.


2
Đây while truebreaklà giải pháp sạch hơn, IMO.
Dan Carley

1
@DanCarley Tôi sẽ không đồng ý với bạn vì lý do là trong câu trả lời được chấp nhận, phiên bản lệnh null, người ta có thể thay thế một giấc ngủ / chờ để cho CPU của bạn nghỉ, và trong trường hợp đó tôi sẽ gọi đó là giải pháp sạch hơn. Vấn đề khác với câu trả lời này là nó yêu cầu người đọc / người dùng hiểu cách thức && hoạt động và làm thế nào nếu lệnh đầu tiên thất bại, nó sẽ không được gọi. Đây chỉ là một ý kiến, giống như của riêng bạn.
Hamid

1
Sự khác biệt chính mà tôi thấy giữa giải pháp này và giải pháp được chấp nhận, là giải pháp này sẽ lặp lại thông báo lỗi "máy chủ không xác định ..." cho đến khi tìm thấy. Để thêm giấc ngủ (ví dụ: mỗi 5 giây):while true; do sleep 5; ping ...
lepe

20

Tôi biết câu hỏi đã cũ ... và đặc biệt hỏi về vấn đề này ping, nhưng tôi muốn chia sẻ giải pháp của mình.

Tôi sử dụng điều này khi khởi động lại máy chủ để biết khi nào tôi có thể SSH lại vào chúng. (Vì pingsẽ trả lời trong vài giây trước khi sshdbắt đầu.)

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

2
Đó chính xác là những gì tôi đã tìm kiếm, cảm ơn! Bạn thậm chí có thể làm gián đoạn cuộc gọi bằng CTRL + C, đây không phải là trường hợp đối với một số giải pháp khác trong chuỗi này.
Alex

1
Lưu ý điều này hoạt động cho các phiên bản BSD của netcat. Phiên bản nmap.org trong các bản phân phối Linux được triển khai khác nhau, vì vậy tùy chọn -z không tồn tại và tùy chọn -w chờ kết nối nhưng không đóng khi thành công. Hoạt động tuyệt vời trong OSX, mặc dù.
Paul

Đây là lý do tại sao bạn không dừng lại ở câu trả lời đầu tiên (tốt). Đây là câu trả lời cho vấn đề thực sự .
Leo

11

Ping máy chủ đích một lần. Kiểm tra xem ping có thành công không (giá trị trả về của ping bằng 0). Nếu máy chủ không còn sống, ping lại.

Mã sau đây có thể được lưu dưới dạng tệp và được gọi với tên máy chủ làm đối số hoặc tước dòng đầu tiên và dòng cuối cùng và được sử dụng làm hàm trong tập lệnh hiện có (tên máy chủ WaitForhost).

Mã không đánh giá nguyên nhân thất bại nếu ping không dẫn đến phản hồi, do đó lặp lại mãi mãi nếu máy chủ không tồn tại. Trang chủ BSD của tôi liệt kê ý nghĩa của từng giá trị trả về, trong khi phiên bản linux thì không, vì vậy tôi đoán đây có thể không phải là di động, đó là lý do tại sao tôi bỏ nó.

#!/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

Bạn có thể xóa chế độ ngủ 1, chỉ ở đây để ngăn chặn mọi sự cố ngập lụt trong trường hợp máy chủ có thể truy cập được nhưng ping sẽ không thoát với mã 0.


4

Xin vui lòng xem các tùy chọn tốt tại stackoverflow . Đây là một mẫu trong bash, bạn sẽ phải lặp qua đoạn mã sau cho đến khi nó trả về kết quả ping thành công.


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

bất kỳ vòng lặp nào ở trên cũng có thể được sử dụng với fping thay vì ping, IMO, phù hợp hơn để sử dụng trong các tập lệnh hơn là chính ping. Xem fping (1) để biết chi tiết.

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

cũng hữu ích để kiểm tra nếu máy hoạt động trước khi làm gì đó với chúng. Một ví dụ đơn giản:

cho h trong HOST1 HOST2 HOST3; làm
  nếu fping -q $ h; sau đó
     tiếng vang -n "$ h:"
     ssh $ h "uname -a"
  fi
làm xong

1

Điều này sẽ thử một số lần nhất định.

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

Thay vì lặp lại $r, bạn có thể kiểm tra nó và hành động theo giá trị của nó:

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

1

Để xử lý độc đáo SIGINT trên BSD ping.

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"

như một chức năng

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

Tôi đã sử dụng chức năng sau đây. Tôi thích nó bởi vì tôi có thể bảo nó ngừng cố gắng sau một thời gian:

#!/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
}

Nó có thể được sử dụng như thế này để khởi chạy một cái gì đó:

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

0

Nói chung, tôi muốn đợi cơ sở dữ liệu của mình hoặc máy chủ khác xuất hiện, nhưng tôi không muốn chờ quá lâu. Đoạn mã sau đợi trong 10 giây, sau đó đặt mã thoát nếu máy chủ không xuất hiện trong thời gian giới hạn.

Nếu máy chủ xuất hiện trước thời hạn, vòng lặp sẽ bị ngắn mạch để bit mã tiếp theo có thể chạy.

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

0

Một cải tiến hơn nữa cho câu trả lời của Gordon Davisson:

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

với '$ ()' xung quanh, một lớp con được bắt đầu và do đó bạn có thể sử dụng Control-C để chấm dứt vòng lặp trong trường hợp máy chủ không khả dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.