Приключилась у меня беда, посыпался один жёсткий диск. Думал его полечить с помощью "Виктории". Но увы, сейчас всё изменилось и диски стали умными.
Раньше можно было пометить плохие секторы, чтобы операционная система туда ничего не писала. Диск работал дальше, только становился меньше объёмом.
Сейчас оказалось что, даже если создать таблицу плохих секторов, она будет проигнорирована и сброшена. Теперь в дисках стоит плата, которая сама пытается восстановить диск, помечает сектор как плохой и использует сектора из резерва. Размер резерва скрывают.
Чтобы диск попытался использовать резервы в плохой сектор должно быть что-то записано. Терять мне нечего, перезаписываю диск нулями. Перехожу в линукс и выполняю команду:
sudo dd if=/dev/zero of=/dev/sdb bs=1M status=progress 1000102428672 bytes (1,0 TB, 931 GiB) copied, 5976 s, 167 MB/s
# через некоторое время
dd: ошибка записи '/dev/sdb': На устройстве не осталось свободного места
953870+0 records in 953869+0 records out 1000204886016 bytes (1,0 TB, 932 GiB) copied, 6061,95 s, 165 MB/s
Пошёл глядеть в "Виктории". Ситуация стала ещё хуже, диск покраснел от плохих секторов. Информация из smart сообщает что, никаких попыток восстановления и переназначения плохих секторов на резервные не было. Вот вам и умные диски.
После этого решил настроить мониторинг здоровья дисков, чтобы держать руку на пульсе, так сказать.
Решил запускать раз в неделю короткий смарт тест и раз в месяц длинный, ну и уведомления слать в телеграм.
Для начала нужно создать телеграм бота.
заходим в телеграм
находим @BotFather
запускаем
вводим команду
/newbotследуем инструкции
Далее нужно узнать свой идентификатор пользователя:
копируем токен бота, выглядит так:
1234567890:AgDk8lNlkjlHbhbBHbDldlkfсоветую его сохранить, он ещё пригодиться
переходим в созданного бота
нажимаем "Start"
переходим в браузер и заходим по адресу:
https://api.telegram.org/bot<ТОКЕН>/getUpdatesв ответе нужно найти "chat":{"id":...} - это и будет твой идентификатор
Можно переходить к скриптам. У меня все мои поделки лежат в домашнем каталоге ~/Scripts
Создаю файл smart-weekly-telegram.sh для еженедельного мониторинга
#!/bin/bash
BOT_TOKEN="токен бота"
CHAT_ID="твой идентификатор"
LOG_FILE="/var/log/smart-weekly/smart-weekly.log"
DATE=$(date '+%Y-%m-%d %H:%M')
mkdir -p /var/log/smart-weekly
send_telegram() {
local message="$1"
curl -s -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \
-d "chat_id=$CHAT_ID" \
-d "text=$message" \
-d "parse_mode=Markdown" >/dev/null 2>&1
}
log_and_send() {
echo "[$DATE] $1" | tee -a "$LOG_FILE"
send_telegram "$1"
}
log_and_send "🔍 Запуск *еженедельного короткого SMART-теста* на $(hostname)"
# для всех дисков
for disk in /dev/sd[a-z]; do
if [ -b "$disk" ]; then
# если диск поддерживает smart
if sudo smartctl -c "$disk" &>/dev/null; then
model=$(sudo smartctl -i "$disk" 2>/dev/null | grep "Device Model\|Model Number" | head -n1 | cut -d: -f2- | xargs)
serial=$(sudo smartctl -i "$disk" 2>/dev/null | grep "Serial Number" | cut -d: -f2- | xargs)
family=$(sudo smartctl -i "$disk" 2>/dev/null | grep "Model Family" | cut -d: -f2- | xargs)
log_and_send "⚙️ Тестирую: *$disk*\nМодель: $model\nСерийный: $serial\nСемейство: $family"
# запускаем короткий тест
sudo smartctl -t short "$disk" >/dev/null 2>&1
# ждём завершения (обычно 2–5 минут, даём 10)
sleep 600
result=$(sudo smartctl -l selftest "$disk" 2>/dev/null | grep "# 1" | head -n1)
if [[ "$result" == *"Завершён без ошибок"* ]]; then
log_and_send "✅ Короткий тест для *$disk* — OK."
else
log_and_send "⚠️ Проблема с *$disk*:\n$result"
fi
# ошибки, любое значение > 0 — плохо
errors=$(sudo smartctl -A "$disk" 2>/dev/null | grep -E "(Reallocated_Sector_Ct|Reallocated_Block_Count|Current_Pending_Sector|Uncorrectable_Error_Count|Reported_Uncorrectable_Errors)" | awk '$10 > 0 {print $2 ": " $10}')
if [ -n "$errors" ]; then
log_and_send "❗ Критично! Проблемы на *$disk*:\n$errors"
fi
fi
fi
done
log_and_send "🔚 Еженедельная SMART-проверка завершена."
Далее создадим файл для ежемесячных длинных тестов, smart-monthly-telegram.sh
#!/bin/bash
BOT_TOKEN="токен бота"
CHAT_ID="твой идентификатор"
LOG_FILE="/var/log/smart-monthly.log"
DATE=$(date '+%Y-%m-%d %H:%M')
mkdir -p /var/log/smart-monthly
send_telegram() {
local message="$1"
curl -s -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" \
-d "chat_id=$CHAT_ID" \
-d "text=$message" \
-d "parse_mode=Markdown" >/dev/null 2>&1
}
log_and_send() {
echo "[$DATE] $1" | tee -a "$LOG_FILE"
send_telegram "$1"
}
log_and_send "🔍 Запуск *ежемесячного расширенного SMART-теста* на $(hostname)"
# для всех дисков
for disk in /dev/sd[a-z]; do
if [ -b "$disk" ]; then
# если диск поддерживает smart
if sudo smartctl -c "$disk" &>/dev/null; then
model=$(sudo smartctl -i "$disk" 2>/dev/null | grep "Device Model\|Model Number" | head -n1 | cut -d: -f2- | xargs)
serial=$(sudo smartctl -i "$disk" 2>/dev/null | grep "Serial Number" | cut -d: -f2- | xargs)
family=$(sudo smartctl -i "$disk" 2>/dev/null | grep "Model Family" | cut -d: -f2- | xargs)
log_and_send "⚙️ Тестирую: *$disk*\nМодель: $model\nСерийный: $serial\nСемейство: $family"
# запускаем длинный тест
sudo smartctl -t long "$disk" >/dev/null 2>&1
# ждём минимум 5 минут перед проверкой
sleep 300
# проверяем статус каждые 10 минут, максимум 25 раз (~4 часа)
for i in {1..25}; do
status_line=$(sudo smartctl -c "$disk" 2>/dev/null | grep "Self-test execution status" | head -n1)
if [[ "$status_line" == *"completed without error"* ]]; then
log_and_send "✅ Тест для *$disk* заверш��н успешно."
break
elif [[ "$status_line" == *"Fatal or unknown error"* ]] || [[ "$status_line" == *"Aborted by host"* ]]; then
log_and_send "❌ Тест для *$disk* завершился с ошибкой:\n$status_line"
break
elif [[ "$status_line" == *"in progress"* ]]; then
if [ $i -eq 25 ]; then
log_and_send "⚠️ Тест для *$disk* не завершился за 4 часа — прерван по таймауту."
fi
else
log_and_send "ℹ️ Статус теста: $status_line"
break
fi
sleep 600
done
# ошибки, любое значение > 0 — плохо
errors=$(sudo smartctl -A "$disk" 2>/dev/null | grep -E "(Reallocated_Sector_Ct|Reallocated_Block_Count|Current_Pending_Sector|Uncorrectable_Error_Count|Reported_Uncorrectable_Errors)" | awk '$10 > 0 {print $2 ": " $10}')
if [ -n "$errors" ]; then
log_and_send "❗ Критично! Проблемы на *$disk*:\n$errors"
fi
# износ SSD, низкое значение — плохо
wear=$(sudo smartctl -A "$disk" 2>/dev/null | grep -E "(Media_Wearout_Indicator|Wear_Leveling_Count|Percent_Lifetime_Used|Available_Reserved_Space)" | awk '$10 < 20 {print $2 ": " $10}')
if [ -n "$wear" ]; then
log_and_send "⚠️ Износ SSD на *$disk*:\n$wear"
fi
fi
fi
done
log_and_send "🔚 Ежемесячная SMART-проверка завершена."
Пояснение по критичным атрибутам:
Reallocated_Sector_Ct - количество секторов на жёстком диске, которые были переназначены из-за ошибок. На SSD может называться Reallocated_Block_Count
(1-10) - нормально даже для новых дисков, иногда брак производства
рост значения со временем - признак физического износа или начала отказа
высокое значение (>50-100) - диск в критическом состоянии, возможна потеря данных
Current_Pending_Sector - количество секторов, которые не удалось прочитать или записать
Uncorrectable_Error_Count - количество ошибок чтения данных, которые не удалось исправить даже с помощью ECC (код для исправления ошибок). Может отображаться как Reported_Uncorrectable_Errors
Media_Wearout_Indicator - показывает оставшийся ресурс износа SSD. Может отображаться как Wear_Leveling_Count, Percent_Lifetime_Used
100 - диск новый
0 - диск изношен
Available_Reserved_Space - остаток резервного пространства для SSD, выделенного для замены изношенных или повреждённых блоков
100 - резерв не использован
10 - осталось 10% от изначального резерва
Как работают счётчики Reallocated_Sector_Ct и Current_Pending_Sector:
сектор повреждается
диск обнаруживает ошибку при чтении/записи
если сектор не удаётся прочитать или записать, он помещается в список pending sectors (Current_Pending_Sector)
при попытке записи в такой сектор диск автоматически переназначает его на резервный сектор из специальной области
после
старый сектор исключается из использования
новый резервный сектор берёт его адрес
счётчик Reallocated_Sector_Ct увеличивается на 1
Как работает Uncorrectable_Error_Count:
при чтении сектора диск автоматически проверяет целостность данных с помощью ECC-кодов
если данные повреждены, но ошибка не большая, ECC исправляет её на лету, пользователь ничего не замечает
если повреждение слишком серьёзное, то ECC не справляется и ошибка считается не корректируемой
ОС получает ошибку ввода/вывода
счётчик Uncorrectable_Error_Count увеличивается
если счётчик растёт со временем, то диск идёт к полному отказу
у исправного диска должно быть 0
Для запуска всего этого дела будем использовать anacron, так как компьютер не включен 27/7.
Требуется сделать скрипты исполняемыми: sudo chmod +x /path/to/your/script.sh
Настроим anacron: sudo nano /etc/anacrontab
В конец файла добавим:
# Ежемесячная SMART-проверка (запускается в первый день месяца, с задержкой 30 минут после включения)
@monthly 30 smart-monthly /home/jhon_mosk/Scripts/smart-monthly-telegram.sh
# Еженедельный короткий SMART-тест
7 10 smart-weekly /home/jhon_mosk/Scripts/smart-weekly-telegram.sh
Ну вот и всё, выглядит примерно так:

А, ну и нужно настроить ротацию логов. Сделаем это через logrotate.
Создадим файл конфигурации: sudo nano /etc/logrotate.d/smart-monthly
/var/log/smart-monthly/smart-monthly.log {
monthly
rotate 6
compress
delaycompress
missingok
notifempty
create 644 root root
}
Переводиться как:
ротация раз в месяц
хранить 6 архивов = полгода
сжимать старые логи
не ругаться, если файла нет
Для еженедельных: sudo nano /etc/logrotate.d/smart-weekly
/var/log/smart-weekly/smart-weekly.log {
weekly
rotate 5
compress
delaycompress
missingok
notifempty
create 644 root root
}
Тоже самое что в ежемесячных, только ротация еженедельная и храниться 5 недель логов
На этом всё. Теперь поломки дисков не станут не неожиданностью.
