Документация — OpsPulse
OpsPulse DOCS
OpsPulse / Документация

Подключение за две минуты

Всё, что нужно для интеграции: один HTTP-запрос из вашего скрипта. Никаких агентов, доступа по SSH и настройки firewall.

01 Как это работает #

OpsPulse работает по принципу «мёртвого выключателя» (dead man’s switch). Вместо того чтобы стучаться к вам на сервер, мы ждём сигнал от вашей задачи. Вы создаёте проверку, получаете персональный Ping URL и вызываете его после успешного завершения скрипта.

Если пинг не пришёл в ожидаемое окно — задача упала, зависла, сервер выключен или cron вообще не запустился. Мы отправляем алерт.

Подойдёт любой HTTP-метод

Мы принимаем GET, POST и HEAD. Тело запроса игнорируется — важен сам факт вызова.

02 Ping URL #

Адрес проверки выглядит так — UUID выдаётся при создании и не меняется:

https://opspulse.ru/ping/550e8400-e29b-41d4-a716-446655440000
Ping URL — это секрет

Кто угодно, зная адрес, может отправить пинг и «замаскировать» реальный сбой. Не публикуйте его в открытых репозиториях. Храните в переменных окружения или в .env.

Удобный вариант — вынести адрес в переменную:

/etc/opspulse.env
# подключается в скрипте: source /etc/opspulse.env
PING_BACKUP=https://opspulse.ru/ping/550e8400-e29b-41d4-a716-446655440000

03 Лимиты и таймауты #

У каждой проверки два независимых параметра: период — как часто вы обещаете присылать пинг, и grace-период — сколько мы ждём сверху, прежде чем поднять тревогу.

ПараметрЗначениеКомментарий
Минимальный период 10 мин / 1 мин 10 минут на тарифе START, от 1 минуты на PRO и PREMIUM.
Максимальный период 365 дней Подходит для редких задач: ротация сертификатов, годовые отчёты.
Grace-период 5 мин Значение по умолчанию, меняется в настройках проверки. Ставьте с запасом на «долгие» дни.
Rate limit 1 / сек Чаще пинговать бессмысленно — лишние запросы отбрасываются с 429.
Повторное напоминание 30 мин PRO и PREMIUM: если проверка не восстановилась, придёт напоминание.
Как выбрать grace-период

Возьмите обычную длительность задачи и умножьте на два. Бэкап на 20 минут → grace 40 минут. Слишком маленький grace даёт ложные алерты, слишком большой — задерживает реальные.

04 Коды ответов #

КодЗначениеЧто делать
200Пинг принят, таймер сброшен.Ничего.
404Проверка с таким UUID не найдена.Сверьте UUID: возможно, проверка удалена или адрес скопирован не полностью.
429Слишком часто.Уменьшите частоту вызовов — таймер уже сброшен предыдущим пингом.
5xxПроблема на нашей стороне.Флаг --retry в curl повторит запрос. Ваш скрипт не пострадает.

05 Crontab #

Самый частый сценарий — мониторинг бэкапов. Оператор && гарантирует, что пинг уйдёт только при успешном завершении команды: если backup.sh вернёт ненулевой код, вторая часть строки не выполнится и вы получите алерт.

Базовый пример

crontab -e
# бэкап в 03:00. Успех → пинг
0 3 * * * /home/user/backup.sh && \
  curl -fsS -m 10 --retry 5 https://opspulse.ru/ping/UUID

Что означают флаги curl

  • -f — считать ошибкой ответ 4xx/5xx, а не «успех с текстом ошибки».
  • -s -S — тихий режим, но ошибки всё же показать. Без этого cron будет присылать вам письма с прогресс-баром.
  • -m 10 — общий таймаут 10 секунд, чтобы запрос не подвесил cron-задачу.
  • --retry 5 — повторить, если сеть мигнула.

Если важно ловить и падения тоже

Вариант выше молчит при ошибке, и алерт придёт по таймауту. Если хотите узнать о падении сразу, а не через grace-период, отправляйте разный сигнал:

crontab -e
0 3 * * * /home/user/backup.sh \
  && curl -fsS -m 10 $PING_BACKUP \
  || curl -fsS -m 10 $PING_BACKUP/fail
Символ % в crontab

В crontab % — специальный символ, его нужно экранировать как \%. Это ломает команды с date +%Y чаще, чем кажется.

06 systemd #

Для юнитов с Type=oneshot используйте ExecStartPost — он выполнится только если основная команда завершилась успешно.

/etc/systemd/system/my-task.service
[Unit]
Description=My Important Task

[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /opt/app/my_script.py
# пинг только при успешном ExecStart
ExecStartPost=/usr/bin/curl -fsS -m 10 https://opspulse.ru/ping/UUID

Если задача запускается таймером, помните: мониторить нужно период таймера, а не сам факт наличия юнита.

/etc/systemd/system/my-task.timer
[Timer]
OnCalendar=daily
Persistent=true

# в OpsPulse: период 24 ч, grace с запасом

07 Bash-скрипты #

Ключевая строка — set -euo pipefail. Без неё скрипт продолжит работу после ошибки и дойдёт до пинга, отрапортовав об успехе, которого не было.

backup.sh
#!/usr/bin/env bash
# -e: выход при ошибке | -u: ошибка на пустой переменной
# -o pipefail: ошибка в любом звене пайпа
set -euo pipefail

PING="https://opspulse.ru/ping/UUID"

echo "Starting backup…"
tar -czf /backup/site.tar.gz /var/www/html
aws s3 cp /backup/site.tar.gz s3://my-bucket/

# дошли до этой строки — значит ошибок не было
curl -fsS -m 10 "$PING"

Пинг при любом выходе через trap

Если нужно сообщать и об успехе, и об ошибке — повесьте обработчик на EXIT. Так пинг уйдёт, даже если скрипт упал в середине.

job.sh
#!/usr/bin/env bash
set -euo pipefail
PING="https://opspulse.ru/ping/UUID"

report() {
  local code=$?
  if [ "$code" -eq 0 ]; then
    curl -fsS -m 10 "$PING" || true
  else
    echo "failed with $code" >&2
  fi
}
trap report EXIT

# … основная работа …
/opt/app/do_work.sh
Зачем || true

Чтобы недоступность OpsPulse не уронила ваш скрипт и не изменила его код выхода. Мониторинг не должен ломать то, что мониторит.

08 Мониторинг диска #

Приём, который выходит за рамки cron: скрипт присылает пинг, только пока условие выполняется. Место закончилось → пинги прекратились → пришёл алерт.

check_disk.sh
#!/usr/bin/env bash
set -uo pipefail

THRESHOLD=90
PING="https://opspulse.ru/ping/UUID"

# процент занятого места на /
USED=$(df --output=pcent / | tr -dc '0-9')

if [ "$USED" -lt "$THRESHOLD" ]; then
  # места хватает → пингуем
  curl -fsS -m 10 "$PING"
else
  # места мало → молчим, OpsPulse поднимет тревогу
  echo "Disk usage ${USED}% >= ${THRESHOLD}%" >&2
fi

Запускайте каждые 10 минут, в настройках проверки поставьте период 10 минут и grace 5 минут. Тем же способом можно следить за длиной очереди, свежестью файла бэкапа или числом процессов.

09 Docker #

Частая ошибка

Указать Ping URL как healthcheck.test напрямую. Тогда контейнер проверяет доступность OpsPulse, а не собственную работоспособность: приложение может лежать, а healthcheck — быть зелёным.

Правильно — сначала проверить своё приложение, и только потом пинговать:

docker-compose.yml
services:
  app:
    image: my-app
    healthcheck:
      test: ["CMD-SHELL",
             "curl -fsS localhost:8000/health && curl -fsS -m 10 $PING_URL"]
      interval: 1m
      timeout: 10s
      retries: 3
    environment:
      PING_URL: https://opspulse.ru/ping/UUID

Разовая задача в контейнере

хост: crontab -e
# дамп БД из контейнера, пинг при успехе
0 4 * * * docker compose exec -T db pg_dump -U app app > /backup/db.sql \
  && curl -fsS -m 10 https://opspulse.ru/ping/UUID

10 Python #

Оберните пинг в try: сбой отправки не должен ломать саму задачу.

task.py
import os, logging
import requests

PING_URL = os.environ["PING_URL"]
log = logging.getLogger("task")


def ping():
    """Пинг не должен ронять задачу."""
    try:
        requests.get(PING_URL, timeout=10).raise_for_status()
    except requests.RequestException as e:
        log.warning("ping failed: %s", e)


def main():
    do_heavy_work()   # упадёт → пинга не будет → придёт алерт
    ping()


if __name__ == "__main__":
    main()

Celery periodic task

tasks.py
from celery import shared_task

@shared_task
def nightly_report():
    build_report()
    ping()   # только после успешной сборки

11 PHP #

file_get_contents() без таймаута может подвесить скрипт, а при ошибке бросит warning. Задайте контекст:

task.php
<?php
// … ваша логика; при ошибке — throw / exit

function opsPing(string $url): void
{
    $ctx = stream_context_create([
        'http' => ['timeout' => 10, 'ignore_errors' => true],
    ]);
    @file_get_contents($url, false, $ctx);
}

opsPing('https://opspulse.ru/ping/UUID');

Если в проекте есть cURL — надёжнее так:

ping-curl.php
$ch = curl_init('https://opspulse.ru/ping/UUID');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 10,
]);
curl_exec($ch);
curl_close($ch);

12 Node.js #

Начиная с Node 18 хватит встроенного fetch без зависимостей.

task.mjs
const PING_URL = process.env.PING_URL;

async function ping() {
  try {
    await fetch(PING_URL, {
      signal: AbortSignal.timeout(10_000),
    });
  } catch (e) {
    console.warn('ping failed:', e.message);
  }
}

try {
  await doHeavyWork();
  await ping();
} catch (e) {
  console.error(e);
  process.exit(1);   // пинга нет → будет алерт
}

13 Go #

main.go
package main

import (
	"log"
	"net/http"
	"os"
	"time"
)

func ping() {
	c := &http.Client{Timeout: 10 * time.Second}
	resp, err := c.Get(os.Getenv("PING_URL"))
	if err != nil {
		log.Printf("ping failed: %v", err)
		return
	}
	resp.Body.Close()
}

func main() {
	if err := doWork(); err != nil {
		log.Fatal(err)   // пинга нет → алерт
	}
	ping()
}

14 Slack #

Создайте incoming webhook и вставьте его в настройках канала уведомлений в OpsPulse.

  1. Откройте api.slack.com/apps и нажмите Create New App.
  2. Выберите From scratch, введите имя (например, OpsPulse) и укажите workspace.
  3. В меню слева — Incoming Webhooks, переведите тумблер в On.
  4. Нажмите Add New Webhook to Workspace и выберите канал.
  5. Скопируйте Webhook URL (вида https://hooks.slack.com/…) и вставьте в OpsPulse.

15 Discord #

  1. Настройки сервера → Integrations.
  2. WebhooksNew Webhook.
  3. Выберите канал для алертов.
  4. Copy Webhook URL → вставьте в OpsPulse.

16 Bitrix24 #

  1. В левом меню — ПриложенияРазработчикам.
  2. Вкладка ДругоеВходящий вебхук.
  3. В правах доступа выберите Чат и уведомления (im).
  4. Сохраните и скопируйте URL из поля Вебхук для вызова REST API.
  5. Вставьте URL в настройки OpsPulse — формат Bitrix определится автоматически.
Webhook-каналы доступны на PRO и PREMIUM

На тарифе START работают Telegram и Email.

17 Частые проблемы #

СимптомВероятная причина
Алерты приходят, хотя задача работает Grace-период меньше реальной длительности задачи. Или в crontab урезанный PATH, и curl не находится — укажите /usr/bin/curl.
Пинг уходит, даже когда скрипт упал Нет set -e, либо использован ; вместо &&.
Cron присылает письма с мусором Забыты флаги -sS у curl.
Ничего не работает после переноса задачи в контейнер В образе нет curl. Поставьте пакет или используйте wget -q -O- URL.
Проверка «мигает» up/down Период короче фактического интервала запуска либо задача запускается не по расписанию.

Проверить связь вручную можно так — в ответ должен прийти код 200:

терминал
curl -sS -o /dev/null -w "%{http_code}\n" \
  https://opspulse.ru/ping/UUID
Готовы?

Первая проверка — 10 секунд

Бесплатный тариф не требует карты. 5 проверок, Telegram и Email.

Создать аккаунт