Як перевірити інтернет-зв’язок з bash?


113

Як можна перевірити підключення до Інтернету, не пінгуючи якийсь веб-сайт? Я маю на увазі, що робити, якщо зв’язок є, але сайт не працює? Чи є перевірка на зв’язок із світом?


2
ping кілька різних сайтів?

1
але я не хочу пінг веб-сайтів, іншого варіанту немає?
lauriys

6
Я просто хочу побачити, що може бути інший спосіб!
lauriys

2
Немає кращого способу, ніж надсилання та отримання одного пакету за набором адрес, за якими ви знаєте, що не переходити в режим офлайн усі відразу, інший спосіб - перевірити поточний набір DNS, якщо ви не хочете, щоб ваша програма запитувала більше загальнодоступних домен.
Тамара Війсман

14
Хочу знати, чи хтось слухає, не видаючи звуку!
Каз

Відповіді:


131

Без пінг

#!/bin/bash

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

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

-q : режим тиші

--spider : не отримуйте, просто перевірте наявність сторінки

$? : код повернення оболонки

0 : оболонка коду "Все в порядку"

Без 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
дуже приємно ... але, звичайно, припускаємо, що в коробці є wget. вбудовані пристрої і те, що, мабуть, не буде. ;)
Ерік Себаста

5
Спробуйте це: echo -e "GET google.com HTTP / 1.0 \ n \ n" | nc google.com 80> / dev / null 2> & 1
user3439968

1
Тут також допоможе tcping. (tcping www.yahoo.com 80) && echo "Сайт працює"
Девід Рамірес

Тут використовується велике пояснення if / else. Дякую !
Даніель-Джеймс Ш

1
@ user3439968 Вам потрібно додати тайм-аут, ncщоб переконатися, що його вичерпано. щось на кшталтnc google.com 80 -w 10
kaptan

93

Здійснення пінг-шлюзу за замовчуванням:

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

14
хороша техніка, її можна модифікувати для використання у функції: function ping_gw() { ... && return 0 || return 1 }а потім використовувати так:ping_gw || (echo "no network, bye" && exit 1)
memnoch_proxy

1
на mac os це не працює через copy-paste: "-bash: ip: команда не знайдена ping: незаконна опція - w"
Benedikt S. Vogler

1
Подає помилкову тривогу, якщо запустити від гостя з віртуалізації, поки хост не підключений.
Teresa e Junior

1
Надає мені помилкові негативи на елементарному ос (0.4.1, Acer Aspire E 15)
Малькольм

1
Будьте обережні з цим. Я просто перевірив це, роблячи, ifconfig down wlan0і у мене все ще є шлюз за замовчуванням, і він є плагінговим, хоча я насправді не можу досягти зовнішнього світу.
Бруно Броноський

29

Супер дякую користувачеві somedrew за їхній пост тут: https://bbs.archlinux.org/viewtopic.php?id=55485 2008-09-20 02:09:48

Оглядати / sys / class / net має бути одним із способів

Ось мій сценарій для перевірки на мережеве з'єднання, яке не є зворотним циклом. Нижче я використовую інший сценарій, який я маю для періодичного тестування, чи доступний мій веб-сайт. Якщо це НЕ доступно, спливаюче вікно повідомляє мене про проблему.

Наведений нижче сценарій не дозволяє мені отримувати спливаючі повідомлення кожні п’ять хвилин, коли мій ноутбук не підключений до мережі.

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

Зверніть увагу на тих, хто не знайшов баш: Остаточний оператор "якщо" перевіряється, якщо НЕ [!] Онлайн, і виходить, якщо це так. Дивіться man bash та шукайте "Вираз може поєднуватися" для отримання більш детальної інформації.

PS Я вважаю, що ping - це не найкраще, ніж тут користуватися, оскільки він спрямований на тестування підключення до певного хоста НЕ перевірити, чи є підключення до будь-якої мережі .

PPS Вище працює на Ubuntu 12.04. / Sys може не існувати в деяких інших дистрибутивах. Дивись нижче:

Сучасні дистрибутиви Linux включають каталог / sys як віртуальну файлову систему (sysfs, порівнянну з / proc, яка є procfs), яка зберігає та дозволяє модифікувати пристрої, підключені до системи, тоді як багато традиційні операційні системи UNIX та Unix використовують / sys як символічне посилання на дерево джерела ядра.

З Вікіпедії https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard


1
Обережно зараз! " cat /sys/class/net/wwan0/carrierНе працює на ubuntu 14.04 LTS.
dotnetCarpenter

1
Можливо, ви хочете, щоб 2>/dev/nullпісля цього cat /sys/class/net/$interface/carrierне було виводу помилок, якщо мережа відключена.
jarno

25

Це працює як на MacOSX, так і на Linux:

#!/bin/bash

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

За винятком osx ( ping: invalid option -- w)
avishayp

fping google.comабо просто fping 8.8.8.8виконує магію з бонусом, ви отримуєте код статусу без необхідності перевіряти його (" google.com is alive") ...
Роджер,

9

У Bash, використовуючи її мережеву обгортку через / dev / { udp , tcp } / host / port :

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

( :це неприйнятне значення Bash, тому що ви просто хочете перевірити з'єднання, але не обробляти його.)


7

Я писав сценарії до цього, просто використовуйте telnet для підключення до порту 80, а потім передайте текст:

HTTP/1.0 GET /index.html

слідом за двома CR / LF послідовностями.

Якщо ви отримаєте якусь форму HTTP-відповіді, ви, як правило, можете припустити, що сайт працює.


3
Навіщо винаходити колесо? curl і wget обидва роблять це ідеально.
Адам Розенфілд,

6
Тому що wget і curl доступні не завжди (наприклад, обмеження у корпоративних середовищах). Telnet був стандартною частиною кожного UNIX з моменту t = 0.
paxdiablo

Так, telnetting був досить стандартним способом тестування з'єднань протягом досить довгого часу.
PTBNL

2
Хороший момент, хоча wget є досить поширеним. Інший варіант - netcat (nc), хоча в цьому випадку це не будь-яке поліпшення порівняно з telnet.
Адам Розенфілд

7

У верхній відповіді пропущено той факт, що ви можете мати ідеально стабільне з'єднання зі своїм шлюзом за замовчуванням, але це не означає, що ви можете дійсно щось досягти в Інтернеті. ОП запитує, як він / вона може перевірити зв’язок із світом. Тому я пропоную змінити основну відповідь, змінивши IP-шлюз на відомий IP (xyzw), який знаходиться поза вашою локальною мережею.

Тож відповідь стане:

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

Видалення також недоброзичливих задників для заміни команд [1] .

Якщо ви просто хочете переконатися, що ви підключені до світу, перш ніж виконати якийсь код, ви також можете скористатися:

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

6

переконайтеся, що ваша мережа дозволяє TCP-трафіку входити і виходити, тоді ви зможете повернути ваш загальнодоступний IP-адресу за допомогою наступної команди

curl ifconfig.co

5

Виконайте таку команду, щоб перевірити, чи працює веб-сайт та яке повідомлення про стан показує веб-сервер:

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

Код статусу "200 ОК" означає, що запит вдався і веб-сайт доступний.


2
Кращою реалізацією може бутиcurl -Is http://www.google.com | head -1 | grep 200; if [[ $? -eq 0 ]]; then; echo "Online"; else; echo "Offline"; fi;
Лука

4

Якщо ваш локальний сервер імен не працює,

ping 4.2.2.1

це легко запам’ятовується IP-адреса, яка завжди запам'ятовується (це фактично навіть сервер імен).


5
ping 8.8.8.8 (Google NS)
користувач3439968

4

Відповідь у верхній частині не працює для MacOS, тому для тих, хто перебуває на комп'ютері Mac, я успішно перевірив це:

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

перевірено на MacOS High Sierra 10.12.6


2
Змініть routeкоманду, щоб route -n get default 2> /dev/null | grep gatewayуникнути написання помилки на stderr в режимі офлайн.
devstuff

4

Цей сценарій bash постійно перевіряє наявність Інтернету та видає звуковий сигнал, коли Інтернет доступний.

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

найкоротший шлях: fping 4.2.2.1=> "4.2.2.1 живе"

Я вважаю за краще це, оскільки це швидший і менш багатослівний вихід, ніж ping, недоліком потрібно буде встановити його.

ви можете використовувати будь-який публічний dns, а не певний веб-сайт.

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

-q повертає вихідний код, тому я лише показую приклад запуску того, що ви перебуваєте в Інтернеті.

встановити на макінтош: brew install fping; на ubuntu:sudo apt-get install fping


2

Пінг був розроблений так, щоб робити саме те, що ви хочете зробити. Однак якщо сайт блокує відлуння ICMP, то ви завжди можете зробити телнет на порт 80 якогось сайту, wget або curl.


2

Перевірка індексної сторінки Google - це ще один спосіб:

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

Подібно до відповіді @ Jesse , цей варіант може бути набагато швидшим, ніж будь-яке рішення з використанням, pingі, можливо, трохи ефективніше, ніж відповідь @ Jesse .

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

Пояснення:

Ця команда використовує findз -execв команду запуску на всі файли не зазначені *lo*в/sys/class/net/ . Це повинні бути посилання на каталоги, що містять інформацію про доступні мережеві інтерфейси на вашій машині.

Команда, що виконується, - це shкоманда, яка перевіряє вміст файлу carrierв цих каталогах. Значення $interface/carrierмає 3 значення - Цитування :

Здається, є три стани:

  • ./carrier не читабельний (наприклад, коли інтерфейс відключений у Менеджері мереж).
  • ./carrier містять "1" (коли інтерфейс активований і він підключений до мережі WiFi)
  • ./carrier містять "0" (коли інтерфейс активований і він не підключений до мережі WiFi)

Перший варіант не вирішено у відповіді @ Jesse . shКоманда смугаста із зовні:

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

catвикористовується для перевірки вмісту carrierта перенаправлення всього виводу на стандартний вихід, навіть коли він не працює, оскільки файл не читається. Якщо серед цих файлів grep -qзнайдено, "1"це означає, що підключено принаймні 1 інтерфейс. Код виходу grep -qбуде остаточним кодом виходу.

Використання

Наприклад, використовуючи статус завершення цієї команди , , ви можете використовувати його , почати gnubiff в вашому ~/.xprofileтільки якщо у вас є підключення до Інтернету.

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 &

Довідково


1

Pong не означає, що веб-служба на сервері працює; це просто означає, що сервер відповідає на відлуння ICMP. Я рекомендую використовувати curl і перевірити його повернене значення.


0

Якщо ваша мета - фактично перевірити доступ до Інтернету , багато з існуючих відповідей на це питання є хибними. Ви повинні пам’ятати про кілька речей:

  1. Можливо, що ваш комп'ютер буде підключений до мережі, не маючи доступу до мережі Інтернет
  2. Можливо, сервер може бути закритим без доступу до Інтернету
  3. Можливо, що портал, що перебуває у полоні, повертає відповідь HTTP за довільною URL-адресою, навіть якщо у вас немає доступу до Інтернету

Зважаючи на це, я вважаю, що найкраща стратегія - зв’язатися з кількома сайтами через HTTPS-з'єднання та повернути правду, якщо хтось із цих сайтів відповість.

Наприклад:

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
}

Використання:

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

Деякі зауваження щодо цього підходу:

  1. Це твердо проти всіх помилкових позитивів і негативів, які я окреслив вище
  2. Усі запити відбуваються паралельно для досягнення максимальної швидкості
  3. Він повернеться помилковим, якщо у вас є технічний доступ до Інтернету, але DNS не функціональний або ваші мережеві налаштування інакше заплутані, що, на мою думку, у більшості випадків робити розумним.

Код повернення з curl не тестується. У моїй системі, якщо мережа недоступна, curl дає rc = 6 (невдала роздільна здатність DNS), але цей код все ще повідомляє "Підключено до Інтернету".
ceperman

@ceperman Код повернення для curl тестується на рядку, де він пише if wait $pid;. Не маю уявлення, чому це не працює у вашій системі. Ви впевнені, що використовуєте bash?
Ajedi32

@ceperman Інша можливість; можливо , один з URL - адрес в списку у верхній фактично робить зворотний успіх для вас, не дивлячись на те, що інші зазнають невдачі дозволу імен?
Ajedi32

2
Мій баш досить базовий, тому я читаю waitі тепер розумію, що код повернення справді тестується. Я повторно скопіював ваш код, і сьогодні він працює - ну! Я, мабуть, щось переплутав останній раз, хоча я не можу зрозуміти, що і як. Тим не менш, mea culpa. Вибачення.
цеперман


-1

Це помітно швидше, ніж будь-яке рішення, розміщене тут, і його також можна використовувати для тестування конкретного хоста .

Хитрість полягає в тому, щоб вирішити IP, використовуючи менш зайнятий вирішувач DNS, ніж той, який використовує 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
Хоча це посилання може відповісти на питання, краще включити сюди суттєві частини відповіді та надати посилання для довідки. Відповіді лише на посилання можуть стати недійсними, якщо пов’язана сторінка зміниться. - З огляду
Девід Бак

Це не стосується конкретної ситуації.
Альберто Сальвія Новелла
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.