Docs

Examples

Copy-paste snippets for pinging FlatLyne from shell, cron, common languages, and schedulers.

This page shows how to ping FlatLyne from the tools your jobs already run in. Every snippet sets a timeout and handles errors, so a slow or failed ping can never hang or crash the job it's monitoring.

The examples use https://api.flatlyne.com/CSps9LOZGccsl2o7ieL0_YrQyZJtkGK_0H1u30FJ-NI as the ping URL. Replace it with the URL from your check's page. Every ping URL accepts both GET and POST, and a successful ping returns 200 with the plain-text body PONG.

Shell and crontab

Add curl after your command with &&, so the ping only goes out when the job succeeds.

crontab
PING_URL=https://api.flatlyne.com/CSps9LOZGccsl2o7ieL0_YrQyZJtkGK_0H1u30FJ-NI
0 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 5 -o /dev/null "$PING_URL"

The first line sets PING_URL, a variable cron passes to the command. Here's what each flag does:

FlagEffect
-fExit non-zero on an HTTP error (such as 404 for a wrong URL) instead of printing the error page.
-sSHide the progress bar, but still print errors.
-m 10Give up on an attempt after 10 seconds.
--retry 5Retry up to 5 times on transient errors: timeouts and HTTP 408, 429, 500, 502, 503 and 504, waiting longer between each try.
-o /dev/nullDiscard the PONG body, so cron doesn't email it to you.

If the host has wget but not curl, use this instead:

crontab
PING_URL=https://api.flatlyne.com/CSps9LOZGccsl2o7ieL0_YrQyZJtkGK_0H1u30FJ-NI
0 2 * * * /usr/local/bin/backup.sh && wget -q -T 10 -t 5 -O /dev/null "$PING_URL"

-T 10 is the timeout and -t 5 is the total number of tries.

Reporting the exit status

Use ; instead of && and append $? to the URL, so the job's exit code goes to FlatLyne either way. 0 counts as success, and any other number marks the check as failed straight away. See Failures, exit codes and start pings for the details.

crontab
PING_URL=https://api.flatlyne.com/CSps9LOZGccsl2o7ieL0_YrQyZJtkGK_0H1u30FJ-NI
0 2 * * * /usr/local/bin/backup.sh; curl -fsS -m 10 --retry 5 -o /dev/null "$PING_URL/$?"

Sending the job's output

Send the job's output as a POST body and it appears with the ping on your check's page. FlatLyne stores the first 10 KB (10,240 bytes) of each body and drops the rest, so send the last 10 KB, where errors usually are.

/usr/local/bin/backup-and-ping.sh
#!/bin/sh
output=$(/usr/local/bin/backup.sh 2>&1)
status=$?
printf '%s\n' "$output" | tail -c 10240 \
  | curl -fsS -m 10 --retry 5 -o /dev/null --data-binary @- \
  "https://api.flatlyne.com/CSps9LOZGccsl2o7ieL0_YrQyZJtkGK_0H1u30FJ-NI/$status"
exit $status

The script exits with the job's own status, so whatever runs it still sees the real result.

Languages

Each snippet reads the ping URL from the FLATLYNE_PING_URL environment variable and defines a small ping helper that logs a failure instead of raising it. Call it with /start before the work, /fail if the work fails, and no suffix when it succeeds.

This version uses only the standard library.

backup.py
import os
import sys
import urllib.request

PING_URL = os.environ["FLATLYNE_PING_URL"]


def ping(suffix=""):
    try:
        with urllib.request.urlopen(PING_URL + suffix, timeout=10):
            pass
    except Exception as exc:  # a failed ping must never fail the job
        print(f"FlatLyne ping failed: {exc}", file=sys.stderr)


ping("/start")
try:
    run_backup()
except Exception:
    ping("/fail")
    raise
ping()

Docker

docker run exits with the container's exit code, so the same && and $? patterns work.

run-backup.sh
docker run --rm registry.example.com/backup-db:1.4; \
  curl -fsS -m 10 --retry 5 -o /dev/null \
  "https://api.flatlyne.com/CSps9LOZGccsl2o7ieL0_YrQyZJtkGK_0H1u30FJ-NI/$?"

Kubernetes CronJob

Run the job and the ping in one shell, report the exit status, then exit with it so Kubernetes still sees the real result. Keep the ping URL in a Secret, and make sure the image includes curl.

backup-db-nightly.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: backup-db-nightly
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: Never
          containers:
            - name: backup
              image: registry.example.com/backup-db:1.4
              command: ["/bin/sh", "-c"]
              args:
                - |
                  /usr/local/bin/backup.sh
                  status=$?
                  curl -fsS -m 10 --retry 5 -o /dev/null \
                    "$PING_URL/$status" || true
                  exit $status
              env:
                - name: PING_URL
                  valueFrom:
                    secretKeyRef:
                      name: flatlyne
                      key: backup-db-nightly-url

GitHub Actions

Ping on success in one step and send a /fail ping in another. continue-on-error stops a failed ping from failing the workflow. Store the ping URL as a repository secret named FLATLYNE_PING_URL.

.github/workflows/nightly.yml
name: Nightly backup
on:
  schedule:
    - cron: "0 2 * * *"

jobs:
  backup:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./scripts/backup.sh
      - name: Ping FlatLyne
        if: success()
        continue-on-error: true
        env:
          PING_URL: ${{ secrets.FLATLYNE_PING_URL }}
        run: curl -fsS -m 10 --retry 5 -o /dev/null "$PING_URL"
      - name: Report failure to FlatLyne
        if: failure()
        continue-on-error: true
        env:
          PING_URL: ${{ secrets.FLATLYNE_PING_URL }}
        run: curl -fsS -m 10 --retry 5 -o /dev/null "$PING_URL/fail"

GitHub can start scheduled workflows late when its runners are busy, so give the check a generous grace period. See Schedules.

systemd timer

ExecStartPost runs only after ExecStart succeeds, so it sends the success ping. The - prefix keeps a failed ping from marking the service as failed. OnFailure starts a second unit that sends the /fail ping.

/etc/systemd/system/backup-db-nightly.service
[Unit]
Description=Nightly database backup
OnFailure=backup-db-nightly-fail.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
ExecStartPost=-/usr/bin/curl -fsS -m 10 --retry 5 -o /dev/null \
  https://api.flatlyne.com/CSps9LOZGccsl2o7ieL0_YrQyZJtkGK_0H1u30FJ-NI
/etc/systemd/system/backup-db-nightly-fail.service
[Unit]
Description=Report a failed nightly backup to FlatLyne

[Service]
Type=oneshot
ExecStart=-/usr/bin/curl -fsS -m 10 --retry 5 -o /dev/null \
  https://api.flatlyne.com/CSps9LOZGccsl2o7ieL0_YrQyZJtkGK_0H1u30FJ-NI/fail
/etc/systemd/system/backup-db-nightly.timer
[Unit]
Description=Run the database backup every night at 02:00

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target

Enable the timer with systemctl enable --now backup-db-nightly.timer.

What's next