Возьмите свой рантайм, подставьте 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 статус-бейджа — копировать руками ничего не нужно:
|| true, try/except, .catch());Подробности — Надёжность пингов.