Как проверить подключение к Интернету с помощью bash?

113

Как можно проверить подключение к Интернету без проверки связи с веб-сайтом? Я имею в виду, что если соединение есть, но сайт не работает? Есть ли проверка на связь с миром?

Lauriys
источник
2
пинговать несколько разных сайтов?
1
но я не хочу пинговать сайты, другого выхода нет?
Lauriys
6
Я просто хочу увидеть, что может быть и другой выход!
lauriys
2
Нет лучшего способа, чем отправка и получение одного пакета по набору адресов, которые, как вы знаете, не должны сразу переходить в автономный режим, другой способ - проверить текущий установленный DNS, если вы не хотите, чтобы ваше приложение пинговало более общедоступный домен.
Тамара Вейсман
14
Я хочу знать, слушает ли кто-нибудь, не издавая ни звука!
Kaz

Ответы:

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
пользователь3439968
источник
2
очень красиво ... но, конечно, предполагается, что в коробке есть wget. встроенные устройства и многое другое, вероятно, не будет. ;)
Эрик Себаста 08
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 с прекрасным объяснением. Спасибо !
Danijel-James W
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 это не работает через копирование и вставку: «-bash: ip: команда не найдена ping: незаконная опция - w»
Бенедикт С. Фоглер,
1
Выдает ложную тревогу, если запускается из гостевой системы виртуализации, когда хост не подключен.
Teresa e Junior
1
Дает ложноотрицательные результаты по elementary os (0.4.1, Acer Aspire E 15)
Малкольм
1
Будьте осторожны с этим. Я только что проверил это на практике, ifconfig down wlan0и у меня все еще есть шлюз по умолчанию, и он доступен для проверки связи, хотя я фактически не могу связаться с внешним миром.
Бруно Броноски
29

Супер Спасибо пользователю somedrew за их сообщение здесь: https://bbs.archlinux.org/viewtopic.php?id=55485 от 20.09.2008 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

Примечание для новичков в bash: последний оператор if проверяет НЕ [!] Онлайн и завершает работу, если это так. См. Man bash и поиск по запросу «Выражения могут быть объединены» для получения более подробной информации.

PS Я считаю, что пинг - не лучшее, что можно здесь использовать, потому что он направлен на проверку соединения с конкретным хостом, а НЕ на проверку наличия соединения с какой- либо сетью .

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 01
1
Вы можете поставить 2>/dev/nullпосле, cat /sys/class/net/$interface/carrierчтобы не выводить ошибку в случае, если сеть отключена.
Ярно
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, потому что вы просто хотите проверить соединение, но не обработку.)

Luchostein
источник
7

Раньше я писал сценарии, которые просто используют telnet для подключения к порту 80, а затем передают текст:

HTTP/1.0 GET /index.html

за которыми следуют две последовательности CR / LF.

Если вы получили ответ HTTP в той или иной форме, вы можете предположить, что сайт работает.

paxdiablo
источник
3
Зачем изобретать велосипед? curl и wget отлично справляются с этим.
Адам Розенфилд
6
Потому что wget и curl доступны не всегда (например, ограничения в корпоративной среде). Telnet был стандартной частью каждой UNIX с момента t = 0.
paxdiablo
Да, телнеттинг уже довольно давно является стандартным способом проверки соединений.
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
Fuwan
источник
6

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

curl ifconfig.co
WaiKit Kung
источник
5

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

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

Код состояния «200 OK» означает, что запрос выполнен и веб-сайт доступен.

Чаминда Бандара
источник
2
Лучшая реализация могла бы бытьcurl -Is http://www.google.com | head -1 | grep 200; if [[ $? -eq 0 ]]; then; echo "Online"; else; echo "Offline"; fi;
Лука Галассо
4

Если ваш локальный сервер имен не работает,

пинг 4.2.2.1

- это легко запоминающийся всегда активный IP (на самом деле это даже сервер имен).

ephemient
источник
5
ping 8.8.8.8 (Google NS)
user3439968 08
4

Топ проголосовали ответ не работает для MacOS так и для тех , кто на макинтош, я успешно проверил это:

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

Франциск0
источник
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

Ping был разработан, чтобы делать именно то, что вы хотите. Однако, если сайт блокирует эхо-запрос ICMP, вы всегда можете подключить telnet к порту 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
dm76
источник
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'

Explenation:

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

Выполняемая команда - это shкоманда, которая проверяет содержимое файла carrierв этих каталогах. Значение $interface/carrierимеет 3 значения - Цитата :

Кажется, есть три состояния:

  • ./carrier не читается (например, когда интерфейс отключен в Network Manager).
  • ./carrier содержат "1" (когда интерфейс активирован и он подключен к сети Wi-Fi)
  • ./carrier содержат "0" (когда интерфейс активирован и он не подключен к сети Wi-Fi)

Первый вариант не рассматривается в ответе @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

Понг не означает, что на сервере запущена веб-служба; это просто означает, что сервер отвечает на эхо ICMP. Я бы рекомендовал использовать curl и проверить его возвращаемое значение.

Томоэ
источник
0

Если ваша цель действительно проверить доступ к Интернету , многие из существующих ответов на этот вопрос ошибочны. Вам следует знать несколько вещей:

  1. Ваш компьютер может быть подключен к сети без доступа к Интернету.
  2. Сервер может выйти из строя, при этом весь интернет будет недоступен
  3. Адаптивный портал может вернуть HTTP-ответ для произвольного URL-адреса, даже если у вас нет доступа в Интернет.

Имея это в виду, я считаю, что лучшая стратегия - связаться с несколькими сайтами через HTTPS-соединение и вернуть true, если какой-либо из этих сайтов отвечает.

Например:

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. Он вернет false, если у вас технически есть доступ в Интернет, но DNS не работает или настройки вашей сети в противном случае испорчены, что я считаю разумным поступком в большинстве случаев.
Ajedi32
источник
Код возврата из curl не проверяется. В моей системе, если сеть недоступна, curl дает rc = 6 (неудачное разрешение DNS), но этот код по-прежнему сообщает «Подключено к Интернету».
ceperman
@ceperman Код возврата для curl проверяется в строке, где он написан if wait $pid;. Понятия не имею, почему это не работает в вашей системе. Вы уверены, что используете bash?
Ajedi32
@ceperman Другая возможность; возможно , один из URL - адресов в списке в верхней фактически делает обратный успех для вас, несмотря на то, что другие терпят неудачу разрешения имен?
Ajedi32
2
Мой bash довольно прост, поэтому я прочитал waitи понял, что код возврата действительно тестируется. Я повторно скопировал ваш код, и сегодня он работает - упс! Должно быть, я что-то напортачил в прошлый раз, хотя не могу понять, что и как. Тем не менее, я виноват. Извинения.
ceperman 03
-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
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - Из отзыва
Дэвид Бак,
Это не относится к данной конкретной ситуации.
Альберто Сальвия Новелла,