Skip to content

How to schedule recurring jobs on a Quake AI VM

How-to · Updated Jun 2026

Coming from another cloud?

▸AWS·Eventbridge Scheduler

This Quake AI feature maps to AWS’s Eventbridge Scheduler.

▸Azure·Automation

This Quake AI feature maps to Azure’s Automation.

▸Google Cloud·Cloud Scheduler

This Quake AI feature maps to Google Cloud’s Cloud Scheduler.

Before this

How to schedule recurring jobs on a Quake AI VM

Run a command or script on a fixed schedule inside a Quake AI instance, using either cron or systemd timers.

Prerequisites

Floating IP requirements#

These scheduling patterns require zero floating IPs. Both cron and systemd timers run entirely inside the guest operating system, so a scheduled job needs no inbound network path. A job that calls the Quake AI API or reaches another instance uses the project's private network, which also needs no floating IP. Allocate a floating IP only if you need to reach the instance directly over SSH from outside the project, and one floating IP per instance covers that access.

Choose cron or systemd timers#

Both mechanisms run a command on a schedule. Pick one per job and keep that job's definition in a single place.

Use cron whenUse systemd timers when
You want the shortest possible setup for a simple recurring commandYou want per-run logging in the system journal
The job is self-contained and has no service dependenciesThe job depends on another unit, the network, or a mounted volume
You are comfortable redirecting output to a file yourselfYou want built-in failure handling, run-time limits, and missed-run catch-up

systemd timers need more configuration upfront and give you logging, dependency ordering, and reliability controls. The rest of this guide shows both, so you can match the mechanism to the job.

Schedule a recurring job#

The example below runs a maintenance script, /usr/local/bin/cleanup-tmp.sh, every day at 02:30 in the instance's local time zone. Replace the script path and schedule with your own.

Each user has a crontab, a table of scheduled commands. Edit the current user's crontab:

bash
crontab -e

Add one line. The five fields are minute, hour, day of month, month, and day of week, followed by the command:

30 2 * * * /usr/local/bin/cleanup-tmp.sh

Save and exit the editor. List the active entries to confirm the change:

bash
crontab -l

The command runs as the user who owns the crontab. For a job that must run as root, install it in the root crontab with sudo crontab -e, or drop a file in /etc/cron.d/:

# /etc/cron.d/cleanup-tmp
30 2 * * * root /usr/local/bin/cleanup-tmp.sh

Files in /etc/cron.d/ include an extra field for the user that runs the command. Keep the schedule readable by adding a comment above each entry that describes what the job does.

Capture output and logs#

A scheduled job produces no terminal output, so route its output somewhere you can read later.

cron mails a job's output to the local user by default, which most cloud instances do not deliver. Redirect both standard output and standard error to a log file in your home directory instead. A user crontab cannot create files under /var/log/ without extra permissions.

Create the log directory, then add the redirect to your crontab:

bash
mkdir -p ~/logs
30 2 * * * /usr/local/bin/cleanup-tmp.sh >> ~/logs/cleanup-tmp.log 2>&1

Rotate the log so it does not grow without bound. logrotate needs the full path to your home directory:

bash
sudo tee /etc/logrotate.d/cleanup-tmp <<EOF
/home/$(whoami)/logs/cleanup-tmp.log {
    weekly
    rotate 8
    compress
    missingok
    notifempty
}
EOF

To write logs under /var/log/, install the job in the root crontab with sudo crontab -e or in /etc/cron.d/ as shown earlier.

Handle failures and overlapping runs#

A job that runs longer than its interval can start a second copy before the first finishes, and a job that fails silently can go unnoticed for days. Guard against both.

Wrap the command in flock to take an exclusive lock, so a slow run blocks the next start instead of overlapping it:

30 2 * * * /usr/bin/flock -n /tmp/cleanup-tmp.lock /usr/local/bin/cleanup-tmp.sh >> ~/logs/cleanup-tmp.log 2>&1

The -n flag makes flock exit immediately if the lock is held, which skips the run rather than queueing it. For failure visibility, have the script exit non-zero on error and append a timestamped status line to its log, then alert on that line with your monitoring agent.

Worked example: schedule a volume snapshot#

A common scheduled job is a recurring volume snapshot. Install the OpenStack CLI and an application credential on the instance, then schedule a snapshot of a target volume.

Create the script at /usr/local/bin/snapshot-data-volume.sh. Set YOUR_CLOUD to the cloud name in your ~/.config/openstack/clouds.yaml or from your downloaded openrc file. See How to generate application credentials.

bash
#!/usr/bin/env bash
set -euo pipefail

export OS_CLOUD=YOUR_CLOUD
VOLUME_ID="YOUR_VOLUME_ID"
STAMP="$(date -u +%Y%m%d-%H%M%S)"

openstack volume snapshot create \
  --volume "$VOLUME_ID" \
  --force \
  "data-volume-$STAMP"

Make the script executable, create the log directory, then schedule it with whichever mechanism you chose above. The cron form runs it nightly at 01:00 UTC under a lock:

bash
chmod +x /usr/local/bin/snapshot-data-volume.sh
mkdir -p ~/logs
0 1 * * * /usr/bin/flock -n /tmp/snapshot-data-volume.lock /usr/local/bin/snapshot-data-volume.sh >> ~/logs/snapshot-data-volume.log 2>&1

Use an application credential rather than a password so the scheduled job keeps working without interactive login. See How to generate application credentials and How to create an instance snapshot for the snapshot lifecycle. Prune old snapshots on the same schedule with a retention loop so the count stays bounded.

Run a dedicated control VM for ops jobs#

Scheduling each job on the instance it acts against works for instance-local maintenance. For jobs that act on many instances or on Quake AI resources through the API, run them from one small, long-lived control instance instead.

A control VM keeps scheduled operations in a single place you can audit and back up, holds one application credential rather than spreading credentials across the fleet, and isolates ops workloads from production traffic. A shared-vCPU flavor is enough for most control workloads. The control VM needs no floating IP of its own when it reaches the Quake AI API and other instances over the project's private network.

Verify the result#

Confirm the schedule is registered and inspect the most recent run.

List the active crontab entries:

bash
crontab -l

After the first scheduled run, check the log file you configured:

bash
tail -n 20 ~/logs/cleanup-tmp.log

See also#

Usage Guidelines

The sample code, software libraries, command line tools, proofs of concept, templates, and other related technology on this page (including any of the foregoing that is provided by Quake AI personnel) is provided to you as Quake AI Content under the Quake AI Customer Agreement, or the relevant written agreement between you and Quake AI (whichever applies). Do not use this Quake AI Content in your production accounts, or on production or other critical data. You are responsible for testing, securing, and optimizing the Quake AI Content (such as sample code) as appropriate for production grade use based on your specific quality control practices and standards. Deploying Quake AI Content may incur Quake AI charges for creating or using Quake AI chargeable resources, such as running Compute instances or storing data in Object Storage. Your use is also subject to the Acceptable Use Policy.

For the full policy, see Usage Guidelines.

Last validated: 27.06.2026

Quick answers

Was this page helpful?