Вопрос или проблема
Я нашел скрипты, которые якобы проверяют наличие интернет-соединения. Некоторые проверяют IP-адрес, если интерфейс активен, НО это не проверяет наличие интернет-соединения. Я нашел некоторые, которые используют ping, например: if [ 'ping google.com -c 4 | grep time' != "" ]; then
, но иногда это может быть ненадежным, так как сам ping может зависнуть по какой-то причине (например, ожидание застрявшего IO).
Есть ли предложения по правильному/надежному способу проверки наличия интернет-соединения с помощью скриптов? Мне нужно использовать какие-то пакеты?
Он должен уметь периодически проверять с помощью cron
, например, а затем выполнять что-нибудь, когда соединение разрывается, например, инициировать ifup --force [interface]
Я настоятельно не рекомендую использовать ping
для определения подключения. Слишком много сетевых администраторов отключают ICMP (протокол, который он использует) из-за опасений относительно атак ping flood, исходящих из их сетей.
Вместо этого я использую быструю проверку надежного сервера на порту, который, как вы можете ожидать, будет открыт:
if nc -zw1 google.com 443; then
echo "у нас есть подключение"
fi
Это использует netcat (nc
) в режиме сканирования портов, быструю проверку (-z
– это режим без ввода/вывода [используется для сканирования]) с быстрой задержкой (-w 1
ждет не более одной секунды, хотя пользователям Apple OS X может потребоваться использовать -G 1
). Он проверяет Google на порте 443 (HTTPS).
Я использовал HTTPS вместо HTTP в качестве усилия по защите от захватных порталов и прозрачных прокси-серверов, которые могут отвечать на порту 80 (HTTP) для любого хоста. Это менее вероятно при использовании порта 443, так как будет несоответствие сертификатов, но это все же случается.
Если вы хотите защититься от этого, вам нужно будет проверить безопасность соединения:
test=google.com
if nc -zw1 $test 443 && echo |openssl s_client -connect $test:443 2>&1 |awk '
$1 == "SSL" && $2 == "handshake" { handshake = 1 }
handshake && $1 == "Verification:" { ok = $2; exit }
END { exit ok != "OK" }'
then
echo "у нас есть подключение"
fi
Это проверяет наличие соединения (вместо ожидания, пока openssl завершит выполнение) и затем выполняет SSL рукопожатие, сосредотачиваясь на этапе проверки. Он тихо завершает работу (“истина”), если проверка была “ОК”, или завершает с ошибкой (“ложь”), затем мы сообщаем о находке.
Код awk анализирует вывод openssl
построчно:
- Если первое слово в строке “SSL”, а второе “Verification”, установите
handshake
в1
- Если
handshake
установлен и первое слово в строке “Verification”,
то сохраните второе слово (статус проверки) вok
и прекратите чтение - Выйдите со значением
0
(истина), если статус проверки былOK
, или выйдите со значением1
(ложь).
Мы используем!=
здесь, потому что коды выхода из shell обратны
(Особенность awk: Вызов exit
во время чтения строк просто прекращает чтение строк и переходит к условию END
, из которого можно действительно exit
.)
Тестирование IPv4 соединения
Если ваша сеть пропускает ICMP-запросы, попробуйте отправить ping на 8.8.8.8 (сервер, который управляется Google).
if ping -q -c 1 -W 1 8.8.8.8 >/dev/null; then
echo "IPv4 активно"
else
echo "IPv4 неактивно"
fi
Тестирование IP-соединения и DNS
Если вы хотите, чтобы тест завершился успешно только тогда, когда DNS также работает, используйте имя хоста.
if ping -q -c 1 -W 1 google.com >/dev/null; then
echo "Сеть активна"
else
echo "Сеть неактивна"
fi
Тестирование интернет-соединения
Некоторые брандмауэры блокируют ICMP-запросы. В некоторых местах есть брандмауэр, который блокирует весь трафик, кроме веб-прокси. Если вы хотите протестировать интернет-соединение, вы можете выполнить HTTP-запрос.
case "$(curl -s --max-time 2 -I http://google.com | sed 's/^[^ ]* *\([0-9]\).*/\1/; 1q')" in
[23]) echo "HTTP-соединение активно";;
5) echo "Веб-прокси не позволяет проходить дальше";;
*) echo "Сеть неактивна или очень медленная";;
esac
Я сделал скрипт, который использует несколько способов проверки интернет-соединения (ping, nc и curl, благодаря Adam Katz, Gilles и Archemar). Надеюсь, это будет полезно кому-то. Смело редактируйте его на свой вкус/оптимизируйте.
Проверяет ваш шлюз, DNS и интернет-соединение (с использованием curl, nc и ping).
Поместите это в файл, затем сделайте его исполняемым (обычно sudo chmod +x filename
)
#!/bin/bash
GW=`/sbin/ip route | awk '/default/ { print $3 }'`
checkdns=`cat /etc/resolv.conf | awk '/nameserver/ {print $2}' | awk 'NR == 1 {print; exit}'`
# google.com выдает ошибку 301/Перемещено
checkdomain=www.google.com
#несколько функций
function portscan
{
tput setaf 6; echo "Начало сканирования порта $checkdomain порт 80"; tput sgr0;
if nc -zw1 $checkdomain 80; then
tput setaf 2; echo "Сканирование порта успешно, $checkdomain порт 80 доступен"; tput sgr0;
else
echo "Сканирование порта $checkdomain порт 80 не удалось."
fi
}
function pingnet
{
#Google имеет самое надежное имя хоста. Смело меняйте его.
tput setaf 6; echo "Отправляю ping на $checkdomain для проверки интернет-соединения." && echo; tput sgr0;
ping $checkdomain -c 4
if [ $? -eq 0 ]
then
tput setaf 2; echo && echo "$checkdomain доступен. Интернет-соединение, вероятно, доступно."&& echo ; tput sgr0;
#Вставьте любую команду, которую вы хотите здесь
else
echo && echo "Не удалось установить интернет-соединение. Здесь может быть что-то не так." >&2
#Вставьте любую команду, которую вы хотите здесь
# exit 1
fi
}
function pingdns
{
#Захватите первый DNS-сервер из /etc/resolv.conf
tput setaf 6; echo "Отправляю ping на первый DNS-сервер в resolv.conf ($checkdns) для проверки разрешения имен" && echo; tput sgr0;
ping $checkdns -c 4
if [ $? -eq 0 ]
then
tput setaf 6; echo && echo "$checkdns доступен для ping. Продолжаю проверку домена."; tput sgr0;
#Вставьте любую команду, которую вы хотите здесь
else
echo && echo "Не удалось установить интернет-соединение с DNS. Здесь может быть что-то не так." >&2
#Вставьте любую команду, которую вы хотите здесь
# exit 1
fi
}
function httpreq
{
tput setaf 6; echo && echo "Проверка HTTP-соединения"; tput sgr0;
case "$(curl -s --max-time 2 -I $checkdomain | sed 's/^[^ ]* *\([0-9]\).*/\1/; 1q')" in
[23]) tput setaf 2; echo "HTTP-соединение активно"; tput sgr0;;
5) echo "Веб-прокси не позволяет проходить дальше";exit 1;;
*)echo "Что-то не так с HTTP-соединениями. Проверьте это."; exit 1;;
esac
# exit 0
}
#Сначала отправляю ping на шлюз для проверки соединения с ЛВС
tput setaf 6; echo "Отправляю ping на шлюз ($GW) для проверки соединения с ЛВС" && echo; tput sgr0;
if [ "$GW" = "" ]; then
tput setaf 1;echo "Нет шлюза. Вероятно отключено..."; tput sgr0;
# exit 1
fi
ping $GW -c 4
if [ $? -eq 0 ]
then
tput setaf 6; echo && echo "Шлюз ЛВС доступен для ping. Продолжается проверка интернет-соединения."; tput sgr0;
pingdns
pingnet
portscan
httpreq
exit 0
else
echo && echo "Что-то не так с ЛВС (шлюз недоступен)"
pingdns
pingnet
portscan
httpreq
#Вставьте любую команду, которую вы хотите здесь
# exit 1
fi
в интернете много IP-адресов, легкий подход — отправить ping на несколько из них
if ping -c 4 google.com ; then OK ; else KO ; fi
if ping -c 4 facebook.com ; then OK ; else KO ; fi
if ping -c 4 nsa.gov ; then OK ; else KO ; fi # <- возможно, этот не ответит
более полный ответ может включать получение страниц с использованием wget
wget google.com -o google.txt
if parse google.txt ; then OK ; else KO ; fi
где
- parse — это программа, которую вы пишете, чтобы убедиться, что google.txt не является (слишком старой) кешированной версией google.com
благодаря вашим вкладам от каждого пользователя и других веб-ресурсов, мне удалось завершить этот скрипт за 3 дня. и я оставлю его в свободное использование.
этот скрипт автоматизирует обновление IP-адреса при потере соединения, он делает это настойчиво.
#!/bin/bash
# Автор: Джон Ллевелин
# FB: fb.com/johnwilliam.llewelyn
# Twitter: twitter.com/JWLLEWELYN
# Телефон: +584-1491-011-15
# Использование свободно.
# Описание: Монитор подключения для модема ADSL.
# Требования:
# Скопируйте этот код или сохраните в /home/administrator/ConnectionMonitor.sh
# Требуются установленные пакеты fping beep и cron
# Комментируйте blacklist pcspkr snd-pcsp в /etc/modprobe.d/blacklist.conf
# Дайте права на выполнение: chmod +x /home/administrator/ConnectionMonitor.sh
# Добавьте эту строку в crontab -e под пользователем root
# @reboot sleep 120 && /home/administrator/MonitorDeConexion.sh
#################################################################################
# НАСТРОЙКИ
TEST="8.8.8.8" # ТЕСТОВЫЙ PING
ADAPTER1="enp4s0" # ВНЕШНИЙ ЭКСПЕРТНЫЙ АДАПТЕР
# Отчет
LOGFILE=/home/administrator/Documentos/ReportInternet.log
# Сообщения
MESSAGE1="Восстановление подключения..."
MESSAGE2="Подождите немного, пожалуйста..."
MESSAGE3="Нет подключения к интернету."
MESSAGE4="Да, есть подключение к интернету."
#################################################################################
# Дата и время
TODAY=$(date "+%r %d-%m-%Y")
# Показать внешний IP-адрес
IPv4ExternalAddr1=$(ip addr list $ADAPTER1 |grep "inet " |cut -d' ' -f6|cut -d/ -f1)
IPv6ExternalAddr1=$(ip addr list $ADAPTER1 |grep "inet6 " |cut -d' ' -f6|cut -d/ -f1)
# Сигнализация
alarm() {
beep -f 1500 -l 200;beep -f 1550 -l 200;beep -f 1500 -l 200;beep -f 1550 -l 200;beep -f 1500 -l 200;beep -f 1550 -l 200;beep -f 1500 -l 200;beep -f 1550$
}
# Восстановление подключения
resolve() {
clear
echo "$MESSAGE1"
sudo ifconfig $ADAPTER1 up;sudo dhclient -r $ADAPTER1;sleep 5;sudo dhclient $ADAPTER1
echo "$MESSAGE2"
sleep 120
}
# Выполнение работы
while true; do
if [[ "$(fping -I $ADAPTER1 $TEST | grep 'unreachable' )" != "" ]]; then
alarm
clear
echo "================================================================================" >> ${LOGFILE}
echo "$MESSAGE3 - $TODAY" >> ${LOGFILE}
echo "$MESSAGE3 - $TODAY"
echo "================================================================================" >> ${LOGFILE}
sleep 10
resolve
else
clear
echo "================================================================================" >> ${LOGFILE}
echo "$MESSAGE4 - $TODAY - IPv4 Addr: $IPv4ExternalAddr1 - IPv6 Addr: $IPv6ExternalAddr1" >> ${LOGFILE}
echo "$MESSAGE4 - $TODAY - IPv4 Addr: $IPv4ExternalAddr1 - IPv6 Addr: $IPv6ExternalAddr1"
echo "================================================================================" >> ${LOGFILE}
sleep 120
fi
done
pastebin: https://pastebin.com/wfSkpgKA
Я использую следующий скрипт:
#!/bin/bash
_beep() {
( \speaker-test --frequency 400 --test sine -l 1 -p 1 -P 2 >& /dev/null )& # розовый / волнообразный
pid=$!
\sleep 0.5s
\kill -9 $pid
\wait $pid 2>/dev/null
}
con=0
while [ true ]; do
if ! ping -c1 -W 2 google.com >& /dev/null; then
echo "Нет интернета..."
con=0
_beep
else
if [[ $con -ne 1 ]]
then
echo "Подключено."
con=1
fi
sleep 1
fi
done
Здесь я объявляю функцию beep
, которая вызывается при сбое ping на сервер Google.
Вопрос:
Есть ли предложения по правильному/надежному способу проверки наличия интернет-соединения с помощью скриптов? Мне нужно использовать какие-то пакеты?
Ответ:
Я использую socat
для проверки сетевого подключения:
socat
(SOcket CAT) – это утилита командной строки, которая устанавливает два двусторонних потока байтов и передает данные между ними. Она достаточно эффективна для проверки сетевого подключения между двумя произвольными точками
while :
do
socat /dev/null TCP4:google.com:443 && break
sleep 60
done
Этот код вводит socat
в бесконечный цикл. Он повторяется до тех пор, пока socat
не “удастся” (возвращает значение $?
равное 0
), в этот момент выполняется break
, и бесконечный цикл завершается для продолжения выполнения скрипта. Это означает, что вы можете проверить свое сетевое подключение прежде чем выполнять оставшуюся часть вашего кода.
Это работает в моей сети, так как у меня ничего не кэшируется на WAN-стороне моего брандмауэра. Если вы знаете сервер более надежный, чем google.com:443
, вы можете использовать его. /dev/null
включен в вызов socat
, потому что socat
требует две точки для соединения, но никакие данные от цели не нужны.
@PNDA предложил извлекать данные из ethtool, что мне нравится. Но я предпочитаю перенаправлять в grep и использовать более простой awk-команду, которую не-башевцы могут быстрее понять. Разница во времени между двумя минимальна.
Используя: Ubuntu Bionic 18.04
Определение сетевого интерфейса:
root@srv:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:1e:67:96:a3:97 brd ff:ff:ff:ff:ff:ff
inet 10.0.1.101/8 brd 10.255.255.255 scope global eno1
valid_lft forever preferred_lft forever
inet6 fe80::21e:67ff:fe96:a397/64 scope link
valid_lft forever preferred_lft forever
3: rename3: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
link/ether 00:1e:67:96:a3:96 brd ff:ff:ff:ff:ff:ff
вывод ethtool:
root@srv:~# ethtool eno1
Настройки для eno1:
Поддерживаемые порты: [ TP ]
Поддерживаемые режимы канала: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Поддерживаемое использование управляющих кадров: Нет
Поддержка авто-согласования: Да
Поддерживаемые режимы FEC: Не сообщается
Рекламируемые режимы канала: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Рекламируемое использование управляющих кадров: Нет
Рекламируемое авто-согласование: Да
Рекламируемые режимы FEC: Не сообщается
Скорость: 1000Мбит/с
Дуплексность: Полный
Порт: Витая пара
PHYAD: 1
Передатчик: внутренний
Автосогласование: вкл
MDI-X: вкл (авто)
Поддержка Wake-on: pumbg
Wake-on: г
Текущий уровень сообщения: 0x00000007 (7)
драйвер проверка связь
Обнаружено соединение: да
Пример команды:
ethtool eno1 | grep "ink detected" | awk '{print $3}'
Выберите своё собственное приключение:
ethtool {{network adapter}} | grep "ink detected" | awk '{print $3}'
Вывод:
Если есть связь:
root@srv:~# ethtool eno1 | grep "ink detected" | awk '{print $3}'
да
Если связи нет:
root@srv:~# ethtool rename3 | grep "ink detected" | awk '{print $3}'
нет
Чтобы избежать ложных срабатываний из-за наличия портала с авторизацией, вам нужно будет проверить вывод соединения HTTP с веб-сайта с предсказуемым содержанием/ответом.
Что-то вроде этого:
#!/bin/sh
detection_out=$(wget -q http://detectportal.firefox.com/success.txt --timeout=10 -O - 2> /dev/null)
test "$detection_out" = "success"
exit $?
Это проверяет, является ли содержимое http://detectportal.firefox.com/success.txt точно идентичным success
.
Вывод дается в виде кода выхода: если код выхода ноль, соединение доступно, в противном случае оно либо недоступно по какой-то причине, либо блокируется порталом с авторизацией.
Я взял этот скрипт отсюда:
https://github.com/libremesh/lime-packages/pull/712/files
Если вам нужен однострочный скрипт или alias для проверки наличия интернет-соединения на Linux или macOS, вы можете использовать это:
[ $(wget --quiet --spider https://google.com &>/dev/null; echo $?) -ne 0 ] && echo "Нет интернета" && exit
адаптировано из: 9 команд для проверки подключения к интернету с примерами скриптов на шелле | GoLinuxCloud
.
Ответ или решение
Вопрос об определении способа проверки подключения к интернету с помощью сценариев на оболочке (shell scripting) является актуальной задачей для специалистов по информационным технологиям. Важно найти надежный и точный метод, который будет эффективно определять наличие подключения к интернету при выполнении сценариев автоматически с использованием, например, cron для периодической проверки.
Теория
Проверка интернет-соединения с использованием сценариев на оболочке может быть сложным процессом, так как он должен учитывать различные аспекты соединения, такие как доступность DNS, ответ сервера HTTP и функциональность сетевых интерфейсов. Существует множество способов для выполнения такой проверки, включая использование команд ping, curl и nc. Однако, каждая из этих команд имеет свои нюансы и ограничения. Например, ICMP-запросы могут быть блокированы на уровне брандмауэра, и команда ping не всегда может дать надежный результат. В то время как использование HTTP-запросов с помощью curl может быть более надежным, так как проверка выполняется через широко использованный порт 80 или 443, который редко бывает закрыт в сети.
Пример
В качестве примера использования различных методов и их комбинирования можно привести сценарий, в котором используется командная утилита nc
(netcat) для быстрой проверки доступности порта 443 на сервере google.com, что говорит о наличии интернет-соединения. Также можно использовать команду curl
для выполнения HTTP-запросов и проверки, доступен ли интернет-сервис.
#!/bin/bash
test=google.com
# Проверка соединения с использованием netcat
if nc -zw1 $test 443; then
echo "Есть соединение"
fi
# Проверка HTTPS соединения и валидации SSL сертификата
if nc -zw1 $test 443 && echo | openssl s_client -connect $test:443 2>&1 | awk '
$1 == "SSL" && $2 == "handshake" { handshake = 1 }
handshake && $1 == "Verification:" { ok = $2; exit }
END { exit ok != "OK" }'
then
echo "SSL соединение установлено"
fi
Данный сценарий проверяет наличие соединения через порт 443 — порт HTTPS, что увеличивает вероятность корректной проверки наличия интернет-соединения.
Применение
Представленный подход можно интегрировать в автоматизированные скрипты, которые запускаются через cron. Это позволит системно отслеживать состояние соединения и выполнять ответные действия, например, принудительную перезагрузку сетевого интерфейса, если соединение отсутствует. Такая практика часто применяется в организациях для обеспечения стабильной работы серверов и устранения проблем с подключением автоматически без участия человека.
Таким образом, выбор инструментов для проверки наличия соединения зависит от сетевой инфраструктуры и ограничений. Использование netcat для тестирования порта, а также curl для проверки доступности веб-сервисов позволяет строить надежные сценарии мониторинга соединения с интернетом. Это особенно ценно для автоматизированных процессов, которые требуют высокого уровня доступности и надежности сетевых соединений.