АйТи Фреш
Главная / Статьи / DevOps и автоматизация
DevOps и автоматизация

ExecCondition вернул код 1: почему служба не запустилась, но systemd не считает её упавшей

Автор: Семёнов Евгений Сергеевич, директор ООО «АйТи-Фреш» · · ~23 мин чтения
ExecCondition вернул код 1: почему служба не запустилась, но systemd не считает её упавшей
Иллюстрация к статье «ExecCondition вернул код 1: почему служба не запустилась, но systemd не считает её упавшей».

Ночной выгрузки бэкапа нет одиннадцать суток, а systemctl status по службе показывает бодрое inactive (dead), ни одного failed. Никто не звонил, мониторинг молчал, в журнале — короткая запись про skipped. Так выглядит правильно понятая, но неправильно применённая директива ExecCondition=. Ниже — что именно systemd делает с кодом возврата проверочного скрипта, чем «отказ от запуска» отличается от аварии, как писать сам скрипт, чтобы случайная ошибка curl не притворялась штатным пропуском, и как ловить такие пропуски мониторингом.

Что на самом деле делает ExecCondition= с кодом возврата

Директива ExecCondition= появилась в systemd 243 и живёт в секции [Service]. Её команды выполняются раньше всего остального — до ExecStartPre=, до ExecStart=. Синтаксис тот же, что у ExecStart=, команд может быть несколько, они идут последовательно. Мануал systemd.service(5) описывает поведение буквально как гибрид ExecStartPre= и проверки условия: когда команда ExecCondition= завершается с кодом от 1 до 254 включительно, оставшиеся команды пропускаются, а юнит не помечается как failed. Если команда вернула 255 или завершилась аномально (таймаут, убита сигналом), юнит считается упавшим. Код 0 или код, перечисленный в SuccessExitStatus=, разрешает продолжить запуск.

Разложу это в таблицу, потому что именно здесь у людей ломается модель. Три разных исхода, а не два — и в этом вся соль. У обычного ExecStartPre= исходов ровно два: ноль — продолжаем, что угодно другое — юнит в failed. У ExecCondition= посередине появляется третий, «тихий» исход, ради которого директива и создавалась.

Внутри systemd этот исход — отдельное значение результата. В исходниках есть enum ServiceResult, и рядом с SERVICE_FAILURE_EXIT_CODE, SERVICE_FAILURE_TIMEOUT, SERVICE_FAILURE_SIGNAL там лежит SERVICE_SKIP_CONDITION. Не разновидность провала, а самостоятельная категория. Поэтому снаружи вы увидите Result=exec-condition, состояние inactive (dead), а вовсе не failed. И — важное следствие — задание, которое запускало службу, завершается успешно: в unit.c при переходе юнита в inactive стартовое задание закрывается как JOB_DONE, а как JOB_FAILED — только если юнит ушёл в failed. Отсюда штука, которая обычно и обманывает скрипты обвязки:

Как это выглядит глазами. В systemctl status юнит показывает Active: inactive (dead), а строка Process: ... ExecCondition=/usr/local/sbin/check-master.sh (code=exited, status=1/FAILURE) подсвечена красным — это единственный визуальный след. В журнале по умолчанию остаётся одна строка уровня info: «pgdump-offsite.service: Skipped due to 'exec-condition'.». Сообщение «Condition check process exited, code=exited, status=1/FAILURE» systemd для пропуска пишет на уровне debug, поэтому без повышенного LogLevel вы его не увидите. Для сравнения, упавший ExecStartPre= даёт в журнале notice о выходе процесса и строку «Failed with result 'exit-code'.», а юнит — в failed.

systemctl start pgdump-offsite.service; echo $?
# 0 — даже если ExecCondition вернул 1 и служба ничего не сделала

systemctl is-failed pgdump-offsite.service; echo $?
# inactive
# 1  — то есть «не упала», формально всё хорошо

systemctl show -p Result -p ActiveState -p ExecCondition pgdump-offsite.service
# Result=exec-condition
# ActiveState=inactive
Запомните три исхода, а не два: 0 — «работаем», 1–254 — «сегодня не моя смена, и это нормально», 255 и аномалии — «проверка сломалась, поднимайте тревогу». Всё, что вы дальше проектируете, опирается на это распределение.

ExecCondition= против ConditionXXX=: кто и что проверяет

В systemd есть два принципиально разных механизма условного запуска, и их регулярно смешивают в одну кучу. Первый — семейство ConditionPathExists=, ConditionPathIsMountPoint=, ConditionHost=, ConditionKernelCommandLine= и десяток их родственников из секции [Unit]. Их вычисляет сам PID 1, внутри себя, без порождения процессов. Это дёшево, это быстро, это выполняется ещё до того, как systemd вообще решит запускать команды. Второй — ExecCondition= из [Service]: это форк, exec, отдельный процесс со всей вашей обвязкой — cgroup, namespace, User=, ProtectSystem=, окружение. Дороже на порядки, зато вы можете проверить что угодно: ответ API, флаг в базе, состояние кластера, наличие свежего файла на удалённой шаре.

Практический вывод простой: если условие выражается штатным Condition*=, берите Condition*=. Я не пишу ExecCondition=/usr/bin/test -e /mnt/arc/flag, когда есть ConditionPathExists=/mnt/arc/flag. Разница ещё и в наблюдаемости: несработавший Condition*= даёт в журнале строку про unmet condition и юнит вообще не начинает стартовать, а несработавший ExecCondition= — уже полноценный запуск с порождением процесса, cgroup и записью в журнал. И да, начиная с 250–251 систему специально приводили в порядок в части того, что именно транслируется наружу по D-Bus как «skipped»: в анонсе systemd 251 отдельно отмечено, что задания, запущенные через StartUnitWithFlags(), больше не возвращают skipped при несработавшем Condition*=, — сигнал JobRemoved вернули к поведению до v250. Если ваша автоматизация опирается на эти сигналы, версия систем важна.

Второе отличие — порядок. ExecCondition= выполняется перед ExecStartPre=, и это ровно то, чего ждёшь. А вот дальше начинается неочевидное: мануал прямо предупреждает, что при любом ненулевом или аномальном выходе ExecCondition= будут выполнены команды ExecStopPost=, как часть остановки службы. То есть ваш «постскрипт», который отправляет уведомление в Telegram или чистит временные файлы, отработает и на штатном пропуске тоже. Я на этом обжигался: в ExecStopPost= висел алерт «задача завершилась», и он честно приходил каждую ночь с резервного узла, где условие штатно не выполнялось.

Третье — те же рекомендации, что и для ExecStartPre=: не запускайте здесь долгоживущие процессы. ExecCondition= укладывается в общий бюджет TimeoutStartSec=, и если проверка ушла в сеть без таймаута и повисла — юнит уедет в failed по таймауту, то есть в тот самый исход, которого вы избегали.

Не дублируйте штатные Condition*= внешними скриптами. ExecCondition= стоит доставать тогда, когда условие нельзя выразить проверкой пути, хоста, виртуализации или параметра ядра.
ExecCondition вернул код 1: почему служба не запустилась, но systemd не считает её упавшей — схема
Схема к статье. Открыть схему в полном размере

Разбор из практики: одиннадцать суток без бэкапа на двух узлах

Рекрутинговая компания, назову её «Найм Профи», 13 рабочих мест, один офис, у нас на обслуживании. Вся работа держится на базе кандидатов и вакансий, поэтому под неё стоят два небольших одинаковых узла Debian 13 (systemd 257), PostgreSQL 17 с потоковой репликацией и плавающий адрес на keepalived. Ночью в 01:30 по таймеру запускается pgdump-offsite.service: делает дамп, шифрует и укладывает во внешнее хранилище. Задача должна выполняться только на текущем мастере — иначе два узла одновременно пишут в одно место и ломают ретеншен.

До нас это было сделано через ExecStartPre= со скриптом check-master.sh. Логика верная, поведение — нет: на резервном узле каждую ночь юнит уходил в failed, в Zabbix прилетал алерт, администратор закрывал его руками. За полгода мы научились закрывать этот алерт не глядя. Классическая усталость от ложных срабатываний. Переписали на ExecCondition= — алерты ушли, все довольны. Ровно до того дня, когда бэкапы перестали делаться совсем.

Что произошло. Скрипт проверки был написан так:

#!/bin/bash
set -euo pipefail

vip=$(curl -s --max-time 5 http://10.20.0.9:8500/v1/kv/db/master?raw)
[ "$vip" = "$(hostname -f)" ]

На резервном узле последняя строка даёт код 1 — штатный пропуск, всё как задумано. А потом в сети переехал DNS-резолвер, curl начал возвращать код 6 (couldn't resolve host), set -e честно завершал скрипт с кодом 6, и systemd видел «код в диапазоне 1–254» — то есть тот же самый штатный пропуск. На обоих узлах. Каждую ночь. Одиннадцать суток подряд юнит аккуратно писал в журнал строку «Skipped due to 'exec-condition'.», оставался в inactive (dead), таймер спокойно планировал следующий запуск, и ни один из наших триггеров, заточенных на systemctl is-failed, ничего не заметил. Обнаружили случайно, при плановой проверке восстановления: последний рабочий архив базы кандидатов оказался двухнедельной давности — для компании, у которой каждый день в работе десятки откликов, это потерянная неделя переписки с соискателями, если бы пришлось восстанавливаться.

Разбор был коротким. Виноват не systemd — он сделал ровно то, что написано в мануале. Виноват договор кодов, которого не было: скрипт использовал «любой ненулевой код» как «не мастер», а любая внутренняя поломка выглядела так же. Починили за час, и с тех пор ни одного незамеченного пропуска.

Если проверка умеет возвращать только «ноль или не ноль», ExecCondition= превращает любую поломку самой проверки в тихий пропуск. Это самая частая и самая дорогая ошибка при работе с этой директивой.
Памятка: Разбор из практики: одиннадцать суток без бэкапа на двух узлах — схема
Памятка: Разбор из практики: одиннадцать суток без бэкапа на двух узлах. Открыть схему в полном размере

Как писать проверочный скрипт: договор кодов 0 / 1 / 255

Правило, к которому мы пришли и которое я теперь ставлю всем: у скрипта ровно три легальных кода выхода, и они описаны в комментарии в его же шапке. 0 — условие выполнено, запускаемся. 1 — условие осознанно не выполнено, это норма, пропускаем. 255 — сама проверка не смогла дать ответ; это авария, юнит должен уйти в failed и разбудить дежурного. Всё остальное — недопустимо, и скрипт обязан сам это исключить.

На bash это делается ловушкой. set -euo pipefail оставляем, но добавляем trap, который любой неожиданный выход превращает в 255. Плюс явные таймауты на всё, что ходит в сеть: и на уровне утилиты, и снаружи через timeout, потому что зависшая проверка съест TimeoutStartSec= юнита и всё равно приведёт к failed, только через минуту-полторы простоя.

#!/bin/bash
# 0   — этот узел мастер, работаем
# 1   — этот узел не мастер, штатный пропуск
# 255 — проверка сломалась, это авария
set -euo pipefail
trap 'exit 255' ERR

me=$(hostname -f)
master=$(timeout 8 curl -sf --max-time 5 \
         http://10.20.0.9:8500/v1/kv/db/master?raw) || exit 255
[ -n "$master" ] || exit 255

if [ "$master" = "$me" ]; then
  exit 0
else
  echo "Не мастер (мастер: $master), пропускаю" >&2
  exit 1
fi

Сам юнит после этого выглядит скучно — и это хорошо. Обратите внимание на два момента: команда ExecCondition= не префиксуется дефисом (префикс — игнорирует код возврата и убивает весь смысл директивы), и путь к скрипту абсолютный, потому что PATH внутри юнита не тот, к которому вы привыкли в интерактивной оболочке. И проверьте, что файл действительно существует: если бинарника нет или у него нет права на исполнение, процесс завершается с кодом 203/EXEC, а он, по логике service.c, попадает в диапазон пропуска — опечатка в пути превратится не в failed, а в вечный тихий skip.

[Unit]
Description=Выгрузка дампа PostgreSQL во внешнее хранилище
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
Type=oneshot
User=pgbackup
TimeoutStartSec=45min
ExecCondition=/usr/local/sbin/check-master.sh
ExecStart=/usr/local/sbin/pgdump-offsite.sh
SyslogIdentifier=pgdump-offsite

Если у вашей проверки семантически осмысленных исходов больше двух — например, «мастер», «реплика» и «идёт плановое обслуживание, тоже пропускаем», — не изобретайте флаг-файлы: просто разведите коды 1 и 2 и оба оставьте в диапазоне пропуска. А если какой-то ненулевой код, наоборот, должен означать «всё в порядке, продолжаем», для этого есть SuccessExitStatus= — коды из этого списка ExecCondition= трактует наравне с нулём. Только помните, что SuccessExitStatus= действует и на основной процесс службы тоже, так что не пишите туда лишнего.

Проверяйте скрипт отдельно от systemd: запустите его руками на обоих узлах и на сломанной сети, посмотрите echo $?. Если в поломанном сценарии вы видите что-то кроме 255 — юнит будет молча пропускать запуски.

Побочные эффекты, о которых не пишут в шпаргалках

Первый — ExecStopPost=. Повторю, потому что это стоило нам ночных уведомлений: любой ненулевой или аномальный выход ExecCondition= запускает команды ExecStopPost=. Штатный пропуск с кодом 1 — тоже ненулевой выход. Если у вас там уведомление или запись в учётную систему «задача отработала», оно поедет каждый раз при пропуске. Лечится либо переносом логики в конец ExecStart=, либо анализом переменной $SERVICE_RESULT внутри самого ExecStopPost=-скрипта: при пропуске там будет exec-condition, а при настоящем провале — exit-code, timeout, signal или core-dump. Оговорка: в таблице значений $SERVICE_RESULT в man systemd.exec строки exec-condition нет, но переменная заполняется из того же поля Result, что показывает systemctl show, — перед тем как опираться на это в бою, один раз проверьте на своей версии.

Второй — взаимодействие с Restart=. Тут важна версия. До systemd 251 служба с Restart=always после несработавшего ExecCondition= перезапускалась, и вы получали бесконечный цикл: проверка говорит «не надо», systemd поднимает снова, проверка снова говорит «не надо». В 251 это исправили, приведя поведение ExecCondition= в соответствие с Condition*=. Если вы работаете на чём-то старее — Ubuntu 20.04 (systemd 245), Debian 11 (247) — не сочетайте ExecCondition= с Restart=always. Для разовых задач по расписанию я в принципе держу Type=oneshot без Restart=, и вопрос снимается.

Третий — таймеры. Пропущенный запуск не ломает расписание: юнит не в failed, таймер продолжает работать штатно и в следующий раз попробует снова. Это ровно то поведение, которого от механизма и ждут, и это главный аргумент в пользу ExecCondition= против «проверка внутри ExecStart= с exit 0» — во втором случае вы теряете различие между «сделал» и «не стал делать» уже на уровне systemd.

Типичный пример, который мы ставим клиентам: ночной таймер копирования на NAS. Если NAS выключен на обслуживание или не отвечает сеть — запуск надо пропустить, а не устраивать ложную аварию; если же сломалась сама проверка — нужен failed. Скрипт проверки при этом держим в том же договоре 0/1/255, адрес NAS — из документационного диапазона для примера:

#!/bin/bash
# /usr/local/sbin/check-nas.sh
# 0 — NAS доступен и смонтирован, 1 — NAS недоступен (пропуск), 255 — авария проверки
trap 'exit 255' ERR
NAS=203.0.113.20
MNT=/mnt/nas-backup

if ! timeout 5 ping -c1 -W2 "$NAS" >/dev/null 2>&1; then
  echo "NAS $NAS не отвечает, пропускаю" >&2
  exit 1
fi
mountpoint -q "$MNT" || { echo "$MNT не смонтирован" >&2; exit 255; }
exit 0
# nas-backup.service
[Service]
Type=oneshot
TimeoutStartSec=2h
ExecCondition=/usr/local/sbin/check-nas.sh
ExecStart=/usr/local/sbin/nas-backup.sh

# nas-backup.timer
[Timer]
OnCalendar=*-*-* 02:00
Persistent=true

[Install]
WantedBy=timers.target

Четвёртый — версии и переносимость. ExecCondition= добавлена в 243, и на старых базах её просто нет: в RHEL-семействе 8 (AlmaLinux 8, Rocky 8, CentOS Stream 8) базовая версия systemd — 239, в Debian 10 — 241. Директива в таком юните будет проигнорирована с руганью в журнале, а служба запустится безусловно — то есть отказ произойдёт в самую опасную сторону. На всём современном парке проблем нет: Debian 12 — 252, Debian 13 — 257, RHEL 9 / AlmaLinux 9 — 252, CentOS Stream 10 — 257, в апстриме к осени 2026 уже 261-я ветка. Но перед раскаткой на зоопарк прогоняйте systemd-analyze verify на каждой платформе — это пять секунд и ноль сюрпризов.

Самый опасный сценарий — не failed и не пропуск, а старая платформа, которая ExecCondition= вообще не понимает. Проверка молча исчезает, и задача выполняется там, где не должна.
Памятка: Побочные эффекты, о которых не пишут в шпаргалках — схема
Памятка: Побочные эффекты, о которых не пишут в шпаргалках. Открыть схему в полном размере

Мониторинг: как отличить штатный пропуск от тихой аварии

Главный вывод из истории «Найм Профи» — не в юните, а в мониторинге. Проверка вида systemctl is-failed по списку служб для задач с ExecCondition= бесполезна: пропущенный юнит никогда не будет failed, это его штатное состояние. Нужны два независимых сигнала. Первый — сам факт, что где-то в кластере задача выполнилась. Второй — что суммарное число пропусков не выходит за ожидаемое.

Первый сигнал я делаю проще всего: успешный ExecStart= в конце трогает файл-маркер (или пишет метку в общее хранилище), а мониторинг смотрит на возраст этого маркера. Не «служба не упала», а «свежий бэкап есть». Такой триггер невозможно обмануть ни пропуском, ни кодом 6 от curl, ни выключенным таймером — он проверяет результат, а не процесс. Порог ставим с запасом на одну итерацию: для ночной задачи — 30 часов.

Второй сигнал — разбор журнала. Пропуски видно и глазами, и машинно:

# что происходило с юнитом за сутки
journalctl -u pgdump-offsite.service --since -24h -o short-iso

# машинно-читаемый итог последнего запуска
systemctl show -p Result -p ExecMainStatus \
  -p InactiveEnterTimestamp pgdump-offsite.service

# отдельный элемент Zabbix: 1 — был штатный пропуск, 0 — не было
journalctl -u pgdump-offsite.service --since -25h --no-pager \
  | grep -ci "exec-condition"

И третий приём, который я советую всем, у кого задача ходит по нескольким узлам: считайте пропуски по кластеру. Из двух узлов ровно один должен отработать и ровно один — пропустить. Два пропуска за ночь означают, что не отработал никто, даже если формально «ни одна служба не упала». Этот триггер у «Найм Профи» и стоит сейчас, и именно он ловит ситуации, когда проверка врёт одинаково на обоих узлах.

Правило: если состояние службы — часть штатного сценария, оно не может быть источником алерта. Мониторьте результат работы, а не состояние юнита.

Когда ExecCondition= не нужен вообще

Скажу прямо: в половине случаев, где я вижу ExecCondition=, он там лишний. Условие «есть ли смонтированный том» закрывается ConditionPathIsMountPoint=. «Только на этой машине» — ConditionHost=. «Только на железе, не в контейнере» — ConditionVirtualization=. «Только если файл-флаг на месте» — ConditionPathExists=. Всё это вычисляет PID 1, без форка, без скрипта, который надо сопровождать и который однажды сломается. Начинайте с них.

Второй случай, когда директива не нужна, — когда «пропуск» на самом деле не пропуск, а нормальная часть работы задачи. Если ваш скрипт умеет сам корректно отработать вхолостую и завершиться с нулём, оставьте это внутри ExecStart=. ExecCondition= нужен ровно тогда, когда вам важно, чтобы systemd знал: запуска не было, ExecStart= не выполнялся вовсе. Это принципиально в двух ситуациях — когда ExecStart= тяжёлый и его нельзя запускать вхолостую, и когда вы строите отчётность по факту запусков.

И честно про спорное. Я знаю коллег, которые вообще не используют ExecCondition=, а всю развилку держат в скрипте с кодом 0 и подробным логом, — аргумент у них тот, что единая точка правды в одном bash-файле проще в сопровождении, чем размазанная по юниту и скрипту логика. Возразить нечему: для одиночного сервера с двумя задачами это рабочая позиция. Разница проявляется на масштабе — когда служб десятки, узлов несколько, а вопрос «эта задача сегодня отработала или сознательно пропустила?» надо задавать не человеку, а машине. Тогда третье состояние в systemd начинает окупаться.

Приоритеты, если начинать прямо сейчас: сначала пройдитесь по юнитам, где стоит ExecCondition=, и проверьте коды возврата скриптов на сломанном сценарии — это ловит настоящие тихие аварии. Потом переведите мониторинг с состояния юнита на возраст результата. Потом уже вычищайте ExecCondition= там, где хватает Condition*=. На последнее можно и забить — работать будет, просто чуть дороже.

Порядок действий: (1) прогнать скрипты проверок на сломанном сценарии и убедиться, что там 255; (2) перевести алерты на возраст результата; (3) заменить самописные проверки штатными Condition*= там, где это возможно.
Памятка: Когда ExecCondition= не нужен вообще — схема
Памятка: Когда ExecCondition= не нужен вообще. Открыть схему в полном размере

Частые вопросы

Почему systemctl status показывает inactive (dead), а не failed, хотя служба ничего не сделала?

Потому что так задумано. Код возврата ExecCondition= в диапазоне 1–254 означает «условие не выполнено», и мануал systemd.service(5) прямо говорит: оставшиеся команды пропускаются, а юнит не помечается как failed. Внутри systemd это отдельный результат SERVICE_SKIP_CONDITION, снаружи он виден как Result=exec-condition. Failed вы получите только при коде 255 или аномальном завершении — таймауте или убийстве сигналом. А вот отсутствующий или неисполняемый скрипт проверки даёт код 203/EXEC и тоже считается пропуском, так что опечатка в пути не вызовет failed.

Как отличить штатный пропуск от того, что сам проверочный скрипт сломался?

Только договором кодов, systemd сам этого не различает. Заведите правило: 0 — работаем, 1 — осознанный пропуск, 255 — проверка не смогла дать ответ. В bash-скрипте это делается через set -euo pipefail плюс trap 'exit 255' ERR и явный || exit 255 на сетевых вызовах. Без этого любая случайная ошибка утилиты (например, код 6 у curl при проблеме с DNS) попадёт в диапазон 1–254 и будет истолкована как нормальный пропуск.

Почему мой ExecStopPost= срабатывает даже тогда, когда служба просто пропустила запуск?

Так описано в мануале: ExecCondition= при любом ненулевом или аномальном выходе запускает команды ExecStopPost= как часть остановки службы. Штатный пропуск с кодом 1 — тоже ненулевой выход. Если в ExecStopPost= у вас уведомление, добавьте внутрь проверку переменной $SERVICE_RESULT: при пропуске там будет exec-condition, при настоящем провале — exit-code, timeout, signal или core-dump.

Можно ли использовать ExecCondition= вместе с Restart=always?

На systemd 251 и новее — да, поведение привели в соответствие с Condition*=, и служба после несработавшей проверки не перезапускается. На версиях 243–250 (это Debian 11 с 247 и Ubuntu 20.04 с 245) вы получите бесконечный цикл перезапусков. Для задач по расписанию я в любом случае предпочитаю Type=oneshot без Restart= и таймер сверху.

Что делать, если на сервере systemd старее 243 и ExecCondition= там нет?

Не полагаться на директиву: она будет проигнорирована с сообщением в журнале, а служба запустится безусловно — то есть отказ произойдёт в опасную сторону. Это касается AlmaLinux/Rocky/CentOS Stream 8 (systemd 239) и Debian 10 (241). Варианты: перенести развилку внутрь ExecStart= с корректным нулевым кодом, использовать штатные ConditionXXX= из секции [Unit] или обновить платформу. Перед раскаткой на разнородный парк прогоняйте systemd-analyze verify.

Как мониторить задачи с ExecCondition=, если systemctl is-failed на них не срабатывает?

Мониторить нужно результат, а не состояние юнита. Практически: успешный ExecStart= трогает файл-маркер или пишет метку в хранилище, а триггер смотрит на возраст этой метки с запасом на одну итерацию расписания. Дополнительно заведите счётчик строк exec-condition в журнале за сутки: в кластере из двух узлов пропусков должно быть ровно один, два пропуска означают, что задача не выполнилась нигде.

Как настроить пропуск ночного бэкапа, если NAS недоступен, и не потерять настоящие аварии?

Поставьте в сервис бэкапа ExecCondition= со скриптом, который возвращает 1, когда NAS не отвечает (штатный пропуск, таймер спокойно отработает в следующую ночь), и 255, когда что-то сломано в самой проверке — например, NAS пингуется, но том не смонтирован. Параллельно мониторьте возраст последней успешной копии: несколько пропусков подряд из-за выключенного NAS — это тоже инцидент, хотя юнит ни разу не будет failed.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 💬 MAX: +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи