Files
2026-test-labor-02/bash/speed_test.sh
2026-06-22 22:38:29 +03:00

281 lines
12 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# ==============================================================================
# Скрипт для замера скорости интернета
# ==============================================================================
# Описание:
# Скрипт выполняет серию последовательных HTTP-запросов к указанному URL,
# замеряет время выполнения и объём скачанных данных, затем вычисляет
# среднюю скорость загрузки в МБ/с (мегабайтах в секунду)
#
# Использование:
# ./speed_test.sh <URL>
#
# Пример:
# ./speed_test.sh https://example.com/large_image.jpg
# ==============================================================================
# Значения по умолчанию
NUM_REQUESTS=10
URL=""
QUIET_MODE=false
ALLOW_COMPRESSION=false
USE_COLOR=true
# ANSI цветовые коды
# Используем их только если цвета включены
COLOR_RESET='\033[0m'
COLOR_BOLD='\033[1m'
COLOR_RED='\033[0;31m'
COLOR_GREEN='\033[0;32m'
COLOR_YELLOW='\033[0;33m'
COLOR_BLUE='\033[0;34m'
COLOR_MAGENTA='\033[0;35m'
COLOR_CYAN='\033[0;36m'
COLOR_WHITE='\033[1;37m'
# Функция для применения цвета (только если цвета включены)
colorize() {
local color="$1"
local text="$2"
if [ "$USE_COLOR" = true ]; then
echo -e "${color}${text}${COLOR_RESET}"
else
echo "$text"
fi
}
# Функция для вывода без новой строки с цветом
colorize_n() {
local color="$1"
local text="$2"
if [ "$USE_COLOR" = true ]; then
echo -ne "${color}${text}${COLOR_RESET}"
else
echo -n "$text"
fi
}
# Функция для вывода справки
show_help() {
echo "Использование: $0 [ОПЦИИ] <URL>"
echo ""
echo "Опции:"
echo " -n, --count NUM Количество запросов (по умолчанию: 10)"
echo " -q, --quiet Тихий режим: выводит только скорость в МБ/с"
echo " -g, --gzip Разрешить HTTP-сжатие (gzip/deflate)"
echo " -c, --no-color Отключить цветной вывод"
echo " -h, --help Показать эту справку"
echo ""
echo "Режимы измерения:"
echo " По умолчанию (без -g):"
echo " Измеряет РЕАЛЬНУЮ скорость интернет-канала"
echo " Отключает gzip-сжатие для точного замера трафика"
echo ""
echo " С опцией -g:"
echo " Измеряет ЭФФЕКТИВНУЮ скорость передачи данных"
echo " Разрешает серверу использовать сжатие"
echo " Полезно для оценки реальной производительности при работе"
echo ""
echo "Примеры:"
echo " $0 https://speedtest.selectel.ru/100MB"
echo " $0 --count 5 https://speedtest.selectel.ru/10MB"
echo " $0 -n 1 https://example.com/image.jpg"
echo " $0 -q -n 3 https://speedtest.selectel.ru/10MB"
echo " $0 --gzip -n 5 https://example.com/large.html"
echo ""
echo "Тихий режим полезен для использования в других скриптах:"
echo " speed=\$($0 -q -n 5 https://speedtest.selectel.ru/10MB)"
echo " echo \"Скорость: \${speed} МБ/с\""
exit 0
}
# Парсинг аргументов командной строки
while [[ $# -gt 0 ]]; do
case $1 in
-n|--count)
# Проверяем, что следующий аргумент существует и является числом
if [ -z "$2" ] || ! [[ "$2" =~ ^[0-9]+$ ]]; then
echo "Ошибка: опция $1 требует числовое значение"
exit 1
fi
NUM_REQUESTS="$2"
shift 2
;;
-q|--quiet)
QUIET_MODE=true
shift
;;
-g|--gzip|--allow-compression)
ALLOW_COMPRESSION=true
shift
;;
-c|--no-color)
USE_COLOR=false
shift
;;
-h|--help)
show_help
;;
-*)
echo "Ошибка: неизвестная опция $1"
echo "Используйте --help для справки"
exit 1
;;
*)
# Это должен быть URL
if [ -z "$URL" ]; then
URL="$1"
else
echo "Ошибка: указано более одного URL"
exit 1
fi
shift
;;
esac
done
# Проверка наличия URL
if [ -z "$URL" ]; then
echo "Ошибка: не указан URL для тестирования"
echo "Использование: $0 [ОПЦИИ] <URL>"
echo "Используйте --help для подробной справки"
exit 1
fi
# Проверка, что количество запросов больше 0
if [ "$NUM_REQUESTS" -le 0 ]; then
echo "Ошибка: количество запросов должно быть больше 0"
exit 1
fi
# Переменные для накопления результатов
total_time=0 # Общее время всех запросов (в секундах)
total_size=0 # Общий объём скачанных данных (в байтах)
# Выводим заголовок только если не в тихом режиме
if [ "$QUIET_MODE" = false ]; then
colorize "$COLOR_CYAN" "=============================================="
colorize "$COLOR_BOLD$COLOR_WHITE" " Замер скорости интернета"
colorize "$COLOR_CYAN" "=============================================="
echo "URL: $URL"
echo "Количество запросов: $NUM_REQUESTS"
if [ "$ALLOW_COMPRESSION" = true ]; then
colorize "$COLOR_YELLOW" "Режим: с HTTP-сжатием (эффективная скорость)"
else
colorize "$COLOR_GREEN" "Режим: без сжатия (реальная скорость канала)"
fi
colorize "$COLOR_CYAN" "=============================================="
echo ""
fi
# Выполняем серию последовательных запросов
for i in $(seq 1 $NUM_REQUESTS); do
# Выводим прогресс только если не в тихом режиме
if [ "$QUIET_MODE" = false ]; then
colorize_n "$COLOR_BLUE" "Запрос $i/$NUM_REQUESTS... "
fi
# Используем curl для загрузки файла
#
# Режим сжатия определяется флагом ALLOW_COMPRESSION:
#
# БЕЗ сжатия (по умолчанию):
# -H "Accept-Encoding: identity" = отключаем gzip/deflate сжатие
# Важно! Без этого сервер может отправить сжатые данные, и мы будем
# измерять размер ПОСЛЕ распаковки, что исказит реальную скорость канала.
# Используйте этот режим для замера РЕАЛЬНОЙ скорости интернет-канала.
#
# С сжатием (опция --gzip):
# Без заголовка Accept-Encoding, curl автоматически запросит gzip
# Сервер может сжать данные, мы получим меньше байт по сети
# Но %{size_download} покажет распакованный размер
# Используйте этот режим для замера ЭФФЕКТИВНОЙ скорости передачи данных
# (полезно для веб-приложений, где сжатие обычно включено)
#
# -s = silent mode (без прогресс-бара)
# -o /dev/null = не сохраняем файл, отправляем в никуда
# -w = форматированный вывод статистики
# %{time_total} = общее время запроса в секундах
# %{size_download} = размер скачанных данных в байтах
# Формируем команду curl в зависимости от режима
if [ "$ALLOW_COMPRESSION" = true ]; then
# Разрешаем сжатие (curl автоматически добавит Accept-Encoding: gzip, deflate)
output=$(curl -s -o /dev/null -w "%{time_total} %{size_download}" "$URL" 2>&1)
else
# Отключаем сжатие для точного замера сетевого трафика
output=$(curl -H "Accept-Encoding: identity" -s -o /dev/null -w "%{time_total} %{size_download}" "$URL" 2>&1)
fi
# Проверяем код возврата curl
if [ $? -ne 0 ]; then
if [ "$QUIET_MODE" = false ]; then
colorize "$COLOR_RED" " ОШИБКА! Не удалось выполнить запрос"
echo "Возможные причины:"
echo " - Неверный URL"
echo " - Нет подключения к интернету"
echo " - Сервер недоступен"
fi
exit 1
fi
# Извлекаем время и размер из вывода curl
request_time=$(echo "$output" | awk '{print $1}')
request_size=$(echo "$output" | awk '{print $2}')
# Проверяем, что получили корректные числа
if [ -z "$request_time" ] || [ -z "$request_size" ]; then
if [ "$QUIET_MODE" = false ]; then
colorize "$COLOR_RED" " ОШИБКА! Не удалось получить данные о запросе"
fi
exit 1
fi
# Накапливаем общее время и размер
total_time=$(echo "$total_time + $request_time" | bc)
total_size=$(echo "$total_size + $request_size" | bc)
# Вычисляем скорость для текущего запроса в МБ/с (только если нужен вывод)
if [ "$QUIET_MODE" = false ]; then
# Размер в байтах / 1048576 = размер в мегабайтах (1 МБ = 1024*1024 байт)
# Скорость = размер_в_МБ / время_в_секундах
speed=$(echo "scale=2; ($request_size / 1048576) / $request_time" | bc)
size_mb=$(echo "scale=2; $request_size / 1048576" | bc)
colorize "$COLOR_GREEN" "✓ OK (${request_time}s, ${size_mb} МБ, ${speed} МБ/с)"
fi
done
# Выводим итоговую статистику только если не в тихом режиме
if [ "$QUIET_MODE" = false ]; then
echo ""
colorize "$COLOR_CYAN" "=============================================="
colorize "$COLOR_BOLD$COLOR_WHITE" " Результаты измерения"
colorize "$COLOR_CYAN" "=============================================="
fi
# Вычисляем средние значения
avg_time=$(echo "scale=4; $total_time / $NUM_REQUESTS" | bc)
total_size_mb=$(echo "scale=2; $total_size / 1048576" | bc)
avg_size_mb=$(echo "scale=2; $total_size_mb / $NUM_REQUESTS" | bc)
# Вычисляем среднюю скорость
# Способ 1: общий объём / общее время (более точный для последовательных запросов)
avg_speed=$(echo "scale=2; $total_size_mb / $total_time" | bc)
# В тихом режиме выводим только скорость
if [ "$QUIET_MODE" = true ]; then
echo "$avg_speed"
else
echo "Выполнено запросов: $NUM_REQUESTS"
echo "Общее время: ${total_time} сек"
echo "Среднее время запроса: ${avg_time} сек"
echo "Общий объём данных: ${total_size_mb} МБ"
echo "Средний объём на запрос: ${avg_size_mb} МБ"
echo ""
colorize "$COLOR_MAGENTA" "=============================================="
colorize "$COLOR_BOLD$COLOR_YELLOW" " СРЕДНЯЯ СКОРОСТЬ: ${avg_speed} МБ/с"
colorize "$COLOR_MAGENTA" "=============================================="
echo ""
fi