Начать
Документация

Сниппеты

Возьмите свой рантайм, подставьте UUID чека — и мониторинг готов. Каждый сниппет шлёт три сигнала, а не только успех.

Почему три сигнала, а не один

Полная таблица суффиксов и правила — на странице Сигналы /start, /fail и длительность.

Код

#!/usr/bin/env bash
PING=https://ping.cronalive.com/<uuid>

# Пинг никогда не должен ронять задачу: || true глушит ошибку сети.
signal() { curl -fsS -m 10 --retry 3 -o /dev/null "$PING$1" || true; }

signal /start
/usr/local/bin/backup.sh
signal "/$?"   # 0 — успех, любой другой код — провал

Скрипт целиком в crontab: 30 2 * * * /usr/local/bin/backup-monitored.sh

import subprocess
import urllib.request

PING = "https://ping.cronalive.com/<uuid>"

def signal(path: str = "") -> None:
    try:
        urllib.request.urlopen(PING + path, timeout=5)
    except Exception:
        pass  # мониторинг не должен ломать задачу

signal("/start")
code = subprocess.call(["/usr/local/bin/backup.sh"])
signal(f"/{code}")

Готовый пакет: pip install cronalive, затем декоратор @cronalive.monitor("<uuid>") или обёртка cronalive run --id <uuid> -- cmd.

const PING = 'https://ping.cronalive.com/<uuid>';

// AbortSignal.timeout — общий бюджет запроса: DNS, соединение и ответ.
const signal = (path = '') => fetch(PING + path, {
    signal: AbortSignal.timeout(5_000),
}).catch(() => {});

await signal('/start');
try {
    await runJob();
    await signal();
} catch (error) {
    await signal('/fail');
    throw error;
}

Готовый пакет: npm i cronalive, затем await monitored("<uuid>", () => runJob()).

<?php

$ping = 'https://ping.cronalive.com/<uuid>';

$signal = static function (string $path = '') use ($ping): void {
    $context = stream_context_create(['http' => [
        'timeout' => 5,
        'ignore_errors' => true,
    ]]);

    @file_get_contents($ping.$path, false, $context);
};

$signal('/start');

try {
    run_job();
    $signal();
} catch (Throwable $e) {
    $signal('/fail');
    throw $e;
}
composer require cronalive/laravel

# .env
CRONALIVE_PING_DOMAIN=https://ping.cronalive.com

// routes/console.php — сигналы ограничены 2 с на соединение и 5 с всего
$schedule->command('my:job')
    ->hourly()
    ->pingCronalive('<uuid>');

Макрос сам шлёт /start до задачи и успех либо /fail после — вручную ничего добавлять не нужно. Штатный thenPing из Laravel так не умеет и ждёт до 30 секунд на сигнал.

# /etc/systemd/system/backup.timer
[Timer]
OnCalendar=*-*-* 03:30:00
Persistent=true

[Install]
WantedBy=timers.target

# /etc/systemd/system/backup.service
[Service]
Type=oneshot
ExecStartPre=/usr/bin/curl -fsS -m 10 --retry 3 -o /dev/null https://ping.cronalive.com/<uuid>/start
ExecStart=/usr/local/bin/backup.sh
ExecStopPost=/usr/bin/curl -fsS -m 10 --retry 3 -o /dev/null https://ping.cronalive.com/<uuid>/$EXIT_STATUS

ExecStopPost выполняется при любом исходе, а $EXIT_STATUS содержит код выхода — отдельная ветка для провала не нужна.

name: nightly-backup

on:
  schedule:
    - cron: '30 2 * * *'

env:
  PING: https://ping.cronalive.com/<uuid>

jobs:
  backup:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - run: curl -fsS -m 10 --retry 3 -o /dev/null "$PING/start"

      - run: ./scripts/backup.sh

      # always() — шаг выполнится и после падения предыдущего.
      - if: always()
        env:
          CODE: ${{ job.status == 'success' && '0' || '1' }}
        run: curl -fsS -m 10 --retry 3 -o /dev/null "$PING/$CODE"

Планировщик GitHub Actions сам по себе ненадёжен: запуски по cron регулярно задерживаются и иногда пропускаются. Именно поэтому чек стоит ставить с запасом по grace.

Те же сниппеты в дашборде

На странице чека UUID уже подставлен, а рядом лежит готовый URL статус-бейджа — копировать руками ничего не нужно:

Общие правила

Подробности — Надёжность пингов.