Làm thế nào để kiểm tra kết nối Internet với bash?


113

Làm cách nào để kiểm tra kết nối internet mà không cần ping một số trang web? Ý tôi là, nếu có kết nối nhưng trang web không hoạt động thì sao? Có kiểm tra kết nối với thế giới không?


2
ping một số trang web khác nhau?

1
nhưng tôi không muốn ping trang web, không có lựa chọn nào khác?
lauriys

6
Tôi chỉ muốn thấy rằng có thể có cách khác!
lauriys

2
Không có cách nào tốt hơn là gửi và nhận một gói tin đến một tập hợp địa chỉ mà bạn biết là không thể ngoại tuyến cùng một lúc, một cách khác là kiểm tra DNS đã đặt hiện tại của bạn nếu bạn không muốn ứng dụng của mình ping công khai hơn. miền.
Tamara Wijsman

14
Tôi muốn biết có ai đang nghe mà không phát ra âm thanh hay không!
Kaz

Câu trả lời:


131

Không cần ping

#!/bin/bash

wget -q --spider http://google.com

if [ $? -eq 0 ]; then
    echo "Online"
else
    echo "Offline"
fi

-q : Chế độ im lặng

--spider : không nhận, chỉ cần kiểm tra tính khả dụng của trang

$?: mã trả lại shell

0 : mã shell "Tất cả OK"

Không có wget

#!/bin/bash

echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1

if [ $? -eq 0 ]; then
    echo "Online"
else
    echo "Offline"
fi

2
rất đẹp ... nhưng tất nhiên giả sử hộp có wget. thiết bị nhúng và những gì không có lẽ sẽ không ;)
Eric Sebasta

5
Hãy thử cách này: echo -e "TẢI google.com HTTP / 1.0 \ n \ n" | nc google.com 80> / dev / null 2> & 1
user3439968

1
tcping cũng sẽ có ích ở đây. (tcping www.yahoo.com 80) && echo "Trang web đã khởi động"
David Ramirez

Câu lệnh if / else sử dụng giải thích wirh ở đây là rất tốt. Cảm ơn bạn !
Danijel-James W

1
@ user3439968 Bạn cần thêm thời gian chờ ncđể đảm bảo hết thời gian. một cái gì đó giống nhưnc google.com 80 -w 10
kaptan

93

Ping cổng mặc định của bạn:

#!/bin/bash
ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error

14
kỹ thuật tốt, nó có thể được sửa đổi để được sử dụng trong một hàm: function ping_gw() { ... && return 0 || return 1 }và sau đó sử dụng như sau:ping_gw || (echo "no network, bye" && exit 1)
memnoch_proxy

1
trên mac os này không làm việc qua copy-dán: "-bash: ip: command not found ping: tùy chọn bất hợp pháp - w"
Benedikt S. Vogler

1
Đưa ra cảnh báo giả nếu chạy từ khách ảo hóa trong khi máy chủ không được kết nối.
Teresa e Junior

1
Mang lại cho tôi âm tính giả trên os tiểu học (0.4.1, Acer Aspire E 15)
Malcolm

1
Hãy cẩn thận với điều này. Tôi vừa thử nghiệm điều này bằng cách thực hiện ifconfig down wlan0và tôi vẫn có một cổng mặc định và nó có thể ping được, mặc dù trên thực tế tôi không thể tiếp cận thế giới bên ngoài.
Bruno Bronosky

29

Cảm ơn người dùng somedrew cho bài đăng của họ ở đây: https://bbs.archlinux.org/viewtopic.php?id=55485 vào 2008-09-20 02:09:48

Tìm kiếm trong / sys / class / net phải là một cách

Đây là tập lệnh của tôi để kiểm tra kết nối mạng không phải là vòng lặp trở lại. Tôi sử dụng phần bên dưới trong một tập lệnh khác mà tôi có để kiểm tra định kỳ xem trang web của tôi có thể truy cập được hay không. Nếu nó KHÔNG thể truy cập được, một cửa sổ bật lên sẽ cảnh báo cho tôi về sự cố.

Tập lệnh bên dưới ngăn tôi nhận thông báo bật lên sau mỗi năm phút bất cứ khi nào máy tính xách tay của tôi không được kết nối với mạng.

#!/usr/bin/bash

# Test for network conection
for interface in $(ls /sys/class/net/ | grep -v lo);
do
  if [[ $(cat /sys/class/net/$interface/carrier) = 1 ]]; then OnLine=1; fi
done
if ! [ $OnLine ]; then echo "Not Online" > /dev/stderr; exit; fi

Lưu ý cho những người mới sử dụng bash: Câu lệnh 'if' cuối cùng kiểm tra nếu KHÔNG phải [!] Trực tuyến và thoát ra nếu đúng như vậy. Xem man bash và tìm kiếm "Biểu thức có thể được kết hợp" để biết thêm chi tiết.

Tái bút Tôi cảm thấy ping không phải là thứ tốt nhất để sử dụng ở đây vì nó nhằm mục đích kiểm tra kết nối với một máy chủ cụ thể KHÔNG kiểm tra xem có kết nối với mạng thuộc bất kỳ loại nào không.

PPS Ở trên hoạt động trên Ubuntu 12.04 / sys có thể không tồn tại trên một số bản phân phối khác. Xem bên dưới:

Các bản phân phối Linux hiện đại bao gồm thư mục / sys như một hệ thống tệp ảo (sysfs, có thể so sánh với / proc, là một procfs), lưu trữ và cho phép sửa đổi các thiết bị được kết nối với hệ thống, trong khi nhiều hệ điều hành giống UNIX và Unix truyền thống sử dụng / sys như một liên kết tượng trưng đến cây nguồn hạt nhân. [cần dẫn nguồn]

Từ Wikipedia https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard


1
Cẩn thận ngay! " cat /sys/class/net/wwan0/carrierKhông hoạt động trên ubuntu 14.04 LTS.
dotnetCarpenter

1
Bạn có thể muốn đặt 2>/dev/nullsau cat /sys/class/net/$interface/carrierđể không xuất hiện lỗi trong trường hợp mạng bị tắt.
jarno

25

Điều này hoạt động trên cả MacOSX và Linux:

#!/bin/bash

ping -q -w1 -c1 google.com &>/dev/null && echo online || echo offline

Trừ OSX ( ping: invalid option -- w)
avishayp

fping google.comhoặc đơn giản là fping 8.8.8.8thực hiện điều kỳ diệu với phần thưởng bạn nhận được mã trạng thái mà không cần phải kiểm tra nó (" google.com is alive") ...
Roger

9

Trong Bash, sử dụng trình bao bọc mạng của nó thông qua / dev / { udp , tcp } / host / port :

if : >/dev/tcp/8.8.8.8/53; then
  echo 'Internet available.'
else
  echo 'Offline.'
fi

( :là Bash no-op, vì bạn chỉ muốn kiểm tra kết nối chứ không muốn xử lý.)


7

Tôi đã viết script trước đó chỉ cần sử dụng telnet để kết nối với cổng 80, sau đó truyền văn bản:

HTTP/1.0 GET /index.html

tiếp theo là hai chuỗi CR / LF.

Với điều kiện bạn nhận lại một số dạng phản hồi HTTP, bạn thường có thể cho rằng trang web đang hoạt động.


3
Tại sao phải phát minh lại bánh xe? curl và wget đều làm điều này một cách hoàn hảo.
Adam Rosenfield

6
Vì không phải lúc nào cũng có sẵn wget và curl (ví dụ: các hạn chế trong môi trường công ty). Telnet đã là một phần tiêu chuẩn của mọi UNIX kể từ thời điểm t = 0.
paxdiablo

Vâng, telnetting đã là một cách khá chuẩn để kiểm tra các kết nối trong một thời gian dài.
PTBNL

2
Điểm tốt, mặc dù wget khá phổ biến. Một tùy chọn khác là netcat (nc), mặc dù trong trường hợp này, nó không phải là bất kỳ cải tiến nào so với telnet.
Adam Rosenfield

7

Câu trả lời hàng đầu bỏ sót thực tế là bạn có thể có kết nối hoàn toàn ổn định với cổng mặc định của mình nhưng điều đó không tự động có nghĩa là bạn thực sự có thể truy cập một thứ gì đó trên internet. OP hỏi làm thế nào anh / cô ấy có thể kiểm tra kết nối với thế giới. Vì vậy, tôi khuyên bạn nên thay đổi câu trả lời hàng đầu bằng cách thay đổi IP cổng thành một IP đã biết (xyzw) nằm ngoài mạng LAN của bạn.

Vì vậy, câu trả lời sẽ trở thành:

ping -q -w 1 -c 1 x.y.z.w > /dev/null && echo ok || echo error

Đồng thời loại bỏ các dấu gạch ngược không có vị trí để thay thế lệnh [1] .

Nếu bạn chỉ muốn đảm bảo rằng bạn được kết nối với thế giới trước khi thực thi một số mã, bạn cũng có thể sử dụng:

if ping -q -w 1 -c 1 x.y.z.w > /dev/null; then
    # more code
fi

6

đảm bảo mạng của bạn cho phép lưu lượng TCP vào và ra, sau đó bạn có thể lấy lại IP công khai của mình bằng lệnh sau

curl ifconfig.co

5

Thực thi lệnh sau để kiểm tra xem một trang web có hoạt động hay không và máy chủ web đang hiển thị thông báo trạng thái nào:

$ curl -Is http://www.google.com | head -1 HTTP/1.1 200 OK

Mã trạng thái '200 OK' có nghĩa là yêu cầu đã thành công và một trang web có thể truy cập được.


2
Cách triển khai tốt hơn có thể làcurl -Is http://www.google.com | head -1 | grep 200; if [[ $? -eq 0 ]]; then; echo "Online"; else; echo "Offline"; fi;
Luca Galasso

4

Nếu máy chủ định danh cục bộ của bạn gặp sự cố,

ping 4.2.2.1

là một IP luôn cập nhật dễ nhớ (thậm chí nó còn là một máy chủ định danh).


5
ping 8.8.8.8 (Google NS)
dùng3439968

4

Các top bình chọn câu trả lời không làm việc cho hệ điều hành MacOS như vậy cho những người trên một mac, tôi đã thử nghiệm thành công này:

GATEWAY=`route -n get default | grep gateway`
if [ -z "$GATEWAY" ]
  then
    echo error
else
  ping -q -t 1 -c 1 `echo $GATEWAY | cut -d ':' -f 2` > /dev/null && echo ok || echo error
fi

đã thử nghiệm trên MacOS High Sierra 10.12.6


2
Thay đổi routelệnh để route -n get default 2> /dev/null | grep gatewaytránh ghi lỗi vào stderr khi ngoại tuyến.
devstuff 19/1218

4

Tập lệnh bash này liên tục kiểm tra Internet và phát ra âm thanh bíp khi Internet khả dụng.

#!/bin/bash
play -n synth 0.3 sine 800 vol 0.75
while :
do
pingtime=$(ping -w 1 8.8.8.8 | grep ttl)
if [ "$pingtime" = "" ] 
then 
   pingtimetwo=$(ping -w 1 www.google.com | grep ttl) 
   if [ "$pingtimetwo" = "" ] 
   then 
       clear ; echo 'Offline'
   else
       clear ; echo 'Online' ; play -n synth 0.3 sine 800 vol 0.75
   fi 
else
    clear ; echo 'Online' ; play -n synth 0.3 sine 800 vol 0.75
fi
sleep 1
done

3

cách ngắn nhất: fping 4.2.2.1=> "4.2.2.1 còn sống"

Tôi thích điều này hơn vì nó nhanh hơn và đầu ra ít dài dòng hơn ping, nhược điểm là bạn sẽ phải cài đặt nó.

bạn có thể sử dụng bất kỳ dns công cộng nào thay vì một trang web cụ thể.

fping -q google.com && echo "do something because you're connected!"

-q trả về mã thoát, vì vậy tôi chỉ hiển thị một ví dụ về việc bạn đang chạy thứ gì đó trực tuyến.

để cài đặt trên mac : brew install fping; trên ubuntu:sudo apt-get install fping


2

Ping được thiết kế để làm chính xác những gì bạn muốn làm. Tuy nhiên, nếu trang web chặn ICMP echo, thì bạn luôn có thể chuyển telnet đến cổng 80 của một số trang web, wget hoặc curl.


2

Kiểm tra trang chỉ mục của Google là một cách khác để thực hiện:

#!/bin/bash

WGET="/usr/bin/wget"

$WGET -q --tries=20 --timeout=10 http://www.google.com -O /tmp/google.idx &> /dev/null
if [ ! -s /tmp/google.idx ]
then
    echo "Not Connected..!"
else
    echo "Connected..!"
fi

2

Tương tự như câu trả lời của @ Jesse , tùy chọn này có thể nhanh hơn nhiều so với bất kỳ giải pháp nào đang sử dụng pingvà có lẽ hiệu quả hơn một chút so với câu trả lời của @ Jesse .

find /sys/class/net/ -maxdepth 1 -mindepth 1 ! -name "*lo*" -exec sh -c 'cat "$0"/carrier 2>&1' {} \; | grep -q '1'

Explenation:

Lệnh này sử dụng lệnh findwith -execđể chạy trên tất cả các tệp không có tên *lo*trong/sys/class/net/ . Đây phải là các liên kết đến các thư mục chứa thông tin về các giao diện mạng có sẵn trên máy của bạn.

Lệnh đang được chạy là shlệnh kiểm tra nội dung của tệp carriertrong các thư mục đó. Giá trị của $interface/carriercó 3 nghĩa - Trích dẫn :

Có vẻ như có ba trạng thái:

  • ./carrier không thể đọc được (ví dụ: khi giao diện bị tắt trong Trình quản lý mạng).
  • ./carrier chứa "1" (khi giao diện được kích hoạt và nó được kết nối với mạng WiFi)
  • ./carrier chứa "0" (khi giao diện được kích hoạt và nó không được kết nối với mạng WiFi)

Lựa chọn đầu tiên không được quan tâm trong câu trả lời của @ Jesse . Các shlệnh sọc ra là:

# Note: $0 == $interface
cat "$0"/carrier 2>&1

catđang được sử dụng để kiểm tra nội dung của carriervà chuyển hướng tất cả đầu ra đến đầu ra chuẩn ngay cả khi nó không thành công vì không thể đọc được tệp. Nếu grep -qtìm thấy "1"trong số các tệp đó có nghĩa là có ít nhất 1 giao diện được kết nối. Mã thoát của grep -qsẽ là mã thoát cuối cùng.

Sử dụng

Ví dụ: bằng cách sử dụng trạng thái thoát của lệnh này, bạn có thể sử dụng nó để bắt đầu một gnubiff trong ~/.xprofilechỉ của bạn nếu bạn có kết nối internet.

online() {
    find /sys/class/net/ -maxdepth 1 -mindepth 1 ! -name "*lo*" -exec sh -c 'cat "$0"/carrier 2>&1 > /dev/null | grep -q "1" && exit 0' {} \;
}
online && gnubiff --systemtray --noconfigure &

Tài liệu tham khảo


1

Pong không có nghĩa là dịch vụ web trên máy chủ đang chạy; nó chỉ có nghĩa là máy chủ đang trả lời ICMP echo. Tôi khuyên bạn nên sử dụng curl và kiểm tra giá trị trả về của nó.


0

Nếu mục tiêu của bạn thực sự là kiểm tra truy cập Internet , thì nhiều câu trả lời hiện có cho câu hỏi này là thiếu sót. Một số điều bạn nên biết:

  1. Máy tính của bạn có thể được kết nối với mạng mà mạng đó không có quyền truy cập internet
  2. Máy chủ có thể gặp sự cố mà toàn bộ mạng internet không thể truy cập được
  3. Cổng bị khóa có thể trả lại phản hồi HTTP cho một URL tùy ý ngay cả khi bạn không có quyền truy cập internet

Với ý nghĩ đó, tôi tin rằng chiến lược tốt nhất là liên hệ với một số trang web qua kết nối HTTPS và trả về true nếu bất kỳ trang web nào phản hồi.

Ví dụ:

connected_to_internet() {
  test_urls="\
  https://www.google.com/ \
  https://www.microsoft.com/ \
  https://www.cloudflare.com/ \
  "

  processes="0"
  pids=""

  for test_url in $test_urls; do
    curl --silent --head "$test_url" > /dev/null &
    pids="$pids $!"
    processes=$(($processes + 1))
  done

  while [ $processes -gt 0 ]; do
    for pid in $pids; do
      if ! ps | grep "^[[:blank:]]*$pid[[:blank:]]" > /dev/null; then
        # Process no longer running
        processes=$(($processes - 1))
        pids=$(echo "$pids" | sed --regexp-extended "s/(^| )$pid($| )/ /g")

        if wait $pid; then
          # Success! We have a connection to at least one public site, so the
          # internet is up. Ignore other exit statuses.
          kill -TERM $pids > /dev/null 2>&1 || true
          wait $pids
          return 0
        fi
      fi
    done
    # wait -n $pids # Better than sleep, but not supported on all systems
    sleep 0.1
  done

  return 1
}

Sử dụng:

if connected_to_internet; then
  echo "Connected to internet"
else
  echo "No internet connection"
fi

Một số lưu ý về cách tiếp cận này:

  1. Nó mạnh mẽ chống lại tất cả các kết quả tích cực và tiêu cực giả mà tôi đã nêu ở trên
  2. Tất cả các yêu cầu đều xảy ra song song để tối đa hóa tốc độ
  3. Nó sẽ trả về false nếu về mặt kỹ thuật bạn có quyền truy cập internet nhưng DNS không hoạt động hoặc cài đặt mạng của bạn bị rối loạn, điều này tôi nghĩ là điều hợp lý nên làm trong hầu hết các trường hợp

Mã trả về từ curl không được kiểm tra. Trên hệ thống của tôi nếu mạng không khả dụng thì curl cho rc = 6 (không phân giải được DNS) nhưng mã này vẫn báo "Đã kết nối với internet".
ceperman

@ceperman Mã trả về cho curl được kiểm tra trên dòng có ghi if wait $pid;. Không biết tại sao nó không hoạt động trên hệ thống của bạn. Bạn có chắc mình đang sử dụng bash?
Ajedi32

@ceperman Một khả năng khác; có lẽ một trong những URL trong danh sách ở trên cùng thực sự mang lại thành công cho bạn, mặc dù những URL khác không phân giải được tên?
Ajedi32

2
Bash của tôi khá cơ bản nên tôi đã đọc tiếp waitvà bây giờ hiểu rằng mã trả về thực sự đang được thử nghiệm. Tôi đã sao chép lại mã của bạn và hôm nay nó hoạt động - rất tiếc! Lần trước chắc tôi đã làm rối tung thứ gì đó mặc dù tôi không thể hiểu cái gì và bằng cách nào. Tuy nhiên, đường cong nhỏ. Xin lỗi.
ceperman


-1

Điều này nhanh hơn đáng kể so với bất kỳ giải pháp nào được đăng ở đây và có thể được sử dụng để kiểm tra một máy chủ cụ thể .

Thủ thuật là giải quyết IP bằng cách sử dụng bộ giải DNS ít bận hơn so với bộ giải được sử dụng bởi ping:

validateConnection () {
    host="${1}"
    ip=$(getent ahostsv4 "${host}" | awk '{ print $1 }' | head -n1)
    ping -c1 "${ip}" 2>&1 >"/dev/null"

    if [ "${?}" -ne 0 ]; then
        echo "No connection to: ${host}" >&2
        exit 1
    fi
}

2
Mặc dù liên kết này có thể trả lời câu hỏi, nhưng tốt hơn hết bạn nên đưa các phần thiết yếu của câu trả lời vào đây và cung cấp liên kết để tham khảo. Các câu trả lời chỉ có liên kết có thể trở nên không hợp lệ nếu trang được liên kết thay đổi. - Từ đánh giá
David Buck

Nó không áp dụng cho tình huống cụ thể này.
Alberto Salvia Novella
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.