Приключилась у меня беда, посыпался один жёсткий диск. Думал его полечить с помощью "Виктории". Но увы, сейчас всё изменилось и диски стали умными.

Раньше можно было пометить плохие секторы, чтобы операционная система туда ничего не писала. Диск работал дальше, только становился меньше объёмом.

Сейчас оказалось что, даже если создать таблицу плохих секторов, она будет проигнорирована и сброшена. Теперь в дисках стоит плата, которая сама пытается восстановить диск, помечает сектор как плохой и использует сектора из резерва. Размер резерва скрывают.

Чтобы диск попытался использовать резервы в плохой сектор должно быть что-то записано. Терять мне нечего, перезаписываю диск нулями. Перехожу в линукс и выполняю команду:

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 недель логов

На этом всё. Теперь поломки дисков не станут не неожиданностью.

Комментарии (23)


  1. UnknownUserMax
    31.10.2025 22:22

    smartd не проще настроить, чем костыли выдумывать?


    1. litos
      31.10.2025 22:22

      smartd шлёт на почту отчеты, хорошо бы научить его слать ещё в телеграм. Хотя тут можно на уровне почты передавать письма скрипту и делать дальше с ними что угодно.


      1. UnknownUserMax
        31.10.2025 22:22

        -M exec ...

        exec PATH - run the executable PATH instead of the default mail
        command, when smartd needs to send email. PATH must point to an
        executable binary file or script


  1. anonymous
    31.10.2025 22:22


    1. dartraiden
      31.10.2025 22:22

      На почту много кто умеет слать, например, виндовый CrystalDiskInfo. Кстати, он опенсорсный, так что технически можно и его научить отправлять в TG.


  1. pudovkin
    31.10.2025 22:22

    Тся.


    1. CoolCmd
      31.10.2025 22:22

      чтобы


  1. morozold
    31.10.2025 22:22

    "Reallocated > 0" и разве этого недостаточно? Надо поглумиться ради хелловина что-ли? Положите его в плов и выкиньте вместе с луком...


    1. Arhammon
      31.10.2025 22:22

      Смотря для чего, для помойки нормально. Для критических применений в утиль от греха подальше. По идее важна вообще динамика появился 1 пендинг>1 релокейт и 5 лет так висит - ну ладно. Ну и в статье мешанина из дисков и твердотельных, которые немножко по разному работают и оцениваются. И восстановить что то викторией итп. никогда ничего было нельзя - можно только до упора писать в не читаемый сектор с надежной что контроллер сам его переназначит.


    1. id_Alex
      31.10.2025 22:22

      "Reallocated > 0" и разве этого недостаточно?

      А есть разница между собственно Reallocated и попыток Reallocated?


      1. Arhammon
        31.10.2025 22:22

        А негде посмотреть попытки переназначения, это нутрянка диска и доступа к ней у простых смертных нет. Есть только уже релокейты/переназначенные сектора и пендинги/кандидаты. Кандидаты - это не обязательно битые сектора, может кривая запись и не может прочитаться и контроллер пометил сектор, а если перезаписать сектор все будет нормально. Это собственно "ремонт" Викторией в режиме Эрейз, Ремап тоже самое только ПО делает очень много попыток записи в сектор.


        1. id_Alex
          31.10.2025 22:22

          Это собственно "ремонт" Викторией в режиме Эрейз, Ремап тоже самое

          т.е. по факту это никакое не лечение? И получается что диск с одним таким сектором может как и долго-долго жить нормально с постоянными перезаписями , так и внезапно окончательно отказать?


          1. Arhammon
            31.10.2025 22:22

            Инфа из смарта не даёт никакой информации по одиночному дефекту в конкретный момент времени. Те дает, но только в 1 варианте: критичная инфа - списываем. Не критичный - одиночный дефект игнорируем и смотрим что будет дальше.

            Более подробной инфы, не у производителя, уже не будет - некому собрать статистику - в бытовухе диски массово уже не используются, в датацентрах их(надеюсь) сразу списывают... Есть те, кто занимаются датарекавери, но к ним диск попадает уже на другом этапе...


  1. aik
    31.10.2025 22:22

    Если вы за reallocated раз в неделю следите, то у меня для вас плохи новости. Ибо если диск сыпется всерьёз, то за неделю он рассыпется окончательно.

    Так что следить за смартом надо в реальном времени. Ну и диски с reallocated переводить в разряд дискеток или мусорных помоек. А за такими можно и не следить.


  1. ZlobniyShurik
    31.10.2025 22:22

    А самое забавное, smart ничего не гарантирует. Попалась мне на одном из серверов парочка дисков с идеальным смартом, при этом на них живого места не было, это уже даже не зомби, а скелеты были (куча секторов со временем чтения 0.3-0.5 секунд, то есть попытки с сотой). Правда, они оба сидели в RAID1 и поэтому OS с них таки грузилась, да, за полчаса, но ведь грузилась :)


    1. MAXXL
      31.10.2025 22:22

      Поддерживаю. недавно было - диски в RAID1, внезапно в журнале системы пошли ошибки по записи на этот рейд. При этом контроллер говорит что с дисками все в порядке, смарт показывает что ошибок нет. А данные пришлось из ночного бэкапа вытаскивать, так как в базе сплошные ошибки.


    1. aik
      31.10.2025 22:22

      Хороший смарт не гарантирует. Но вот плохой смарт обычно всё же гарантирует проблемы.