OmniCube Reference Manual›autosnap(8)

autosnap(8)

System Administration Commands · OmniCube · August 10, 2026

NAME

autosnap - create policy-driven ZFS snapshots of flagged datasets

SYNOPSIS

/opt/omnicube/backup/autosnap [-i NAME]

/opt/omnicube/backup/autosnap -h

DESCRIPTION

autosnap is the creation half of the OmniCube snapshot lifecycle. Driven from cron(8) once an hour, it walks every local ZFS filesystem and volume, keeps those whose user property ${PROPPREFIX}:snapshotting is exactly yes, and creates the periodic snapshots called for by each dataset's snapshot policy. Expiry is the job of autocleansnap(8), replication that of autosync(8).

${PROPPREFIX} is the site prefix read from the SMF property config/site of svc:/omnicube/sysadm:${OC_SMF_INSTANCE:-default} when /opt/omnicube/lib/common/utils.sh is sourced, so all properties below are per-instance and two instances can manage the same pool independently. Run once per instance (see -i), each with its own cron schedule, a dataset flagged ${SITE}:snapshotting=yes and ${SITE2}:snapshotting=yes gets the snapshots of both instances' policies, for example hourly and daily from one and frequent from the other. Selection is

zfs list -H -r -t filesystem,volume -o name,${PROPPREFIX}:snapshotting

with an exact match on the second (tab separated) column, so a value that merely ends in yes selects nothing.

Per dataset, in order: the run-level guard is re-evaluated, so a shutdown starting mid-run stops the job before the next dataset; ${PROPPREFIX}:is_locked is read and the dataset skipped when it is true, meaning another OmniCube job (possibly of another instance) owns the pool; ${PROPPREFIX}:snappolicy is resolved to a file by get_snap_policy_path(), an unset value or - meaning the default policy and an unresolvable one skipping the dataset; the dataset's top-level zpool is marked ${PROPPREFIX}:is_locked=true so cleanup and replication back off; the policy file is sourced after RETENTION has been unset; the due snapshots are created; and the property is inherited away again.

Retention array and scheduling

The policy file is a bash fragment defining the associative array RETENTION; see default.conf(5). Types are considered in the order weekly, daily, hourly, frequent.

RETENTION[TYPE]

Unset or 0 creates no snapshot of that type (the counterpart of the "keep zero" semantic in autocleansnap(8)). -1 also creates none: the type is not handled by this policy (see default.conf(5)). Any other value that is not a string of digits is reported by warning() and skipped, instead of being silently treated as zero by bash arithmetic.

RETENTION[TYPE-time]

When set, the snapshot is created only in the hour matching this value (date '+%H').

RETENTION[TYPE-day]

When set, the snapshot is created only on the day of week matching this value (date '+%u').

The shipped default.conf sets weekly=1, daily=4, hourly=6, frequent=0 and yearly=0, with no -time or -day key, so a dataset on the stock policy gets an hourly snapshot on every run plus a daily and a weekly one whenever that name does not exist yet. Names encode the type and the date:

frequent   ${DS}@frequent-$(date +%y-%W-%d-%H-%M)
hourly     ${DS}@hourly-$(date +%y-%W-%d-%H)
daily      ${DS}@daily-$(date +%y-%W-%d)
weekly     ${DS}@weekly-$(date +%y-%W)
yearly     ${DS}@yearly-$(date +%y)

An existing name is never recreated (is_snapexists()), so running autosnap more often than the coarsest tick is harmless.

Locking and the is_locked trap

One instance runs at a time; the mutex is the directory ${LOCK_BASE}/${logtag}.sync_pool.lock created by acquire_lock_or_exit(). The sync_pool element of that name is historical: it does not interlock with sync_pool.sh(8), which has a lock of its own.

An EXIT HUP INT TERM trap removes the lock directory and inherits ${PROPPREFIX}:is_locked away on the pool being processed. Without it, a kill between the zfs set and the zfs inherit would leave the property stuck at true, which permanently wedges every later autosnap, autosync(8) and autocleansnap(8) run on that pool, since all three skip a locked dataset. The pool is recorded before the property is set, and zfs inherit on an unset property is harmless.

OPTIONS

Options are parsed before /opt/omnicube/lib/common/utils.sh is sourced, because the instance name is baked into ${PROPPREFIX}, ${logtag} and the lock path while sourcing. There are no operands; any other word on the command line is a usage error.

-i NAME
--instance NAME
--instance=NAME

Read configuration from svc:/omnicube/sysadm:NAME instead of :default. This picks the property prefix, hence which datasets are considered (snapshotting), which policy applies (snappolicy) and which is_locked property and lock directory are used. Equivalent to OC_SMF_INSTANCE, which it overrides.

-h, --help

Print the usage block embedded at the top of the script and exit 0.

--

End of options.

USAGE

The sample crontab in /opt/omnicube/share/README runs it hourly at six minutes past, thirty minutes ahead of autocleansnap(8):

6  * * * * /opt/omnicube/backup/autosnap >/dev/null

A second instance beio (its own config/site, say beio) taking frequent snapshots every five minutes of a dataset the default instance already snapshots hourly, with a policy that sets every other type to -1 (see default.conf(5)):

*/5 * * * * /opt/omnicube/backup/autosnap -i beio >/dev/null
pfexec zfs set beio:snapshotting=yes dpool/zones/zethosmariadb01
pfexec zfs set beio:snappolicy=frequent dpool/zones/zethosmariadb01

Flag a dataset for the stock policy (property prefix omnicube here) and run one pass by hand from single-user state:

pfexec zfs set omnicube:snapshotting=yes dpool/zones/zethosmariadb01
pfexec zfs set omnicube:snappolicy=default dpool/zones/zethosmariadb01
OC_IGNORE_RUNLEVEL=1 pfexec /opt/omnicube/backup/autosnap

Recover from a hard kill that left both halves of the lock behind:

pfexec zfs inherit omnicube:is_locked dpool
pfexec rmdir /var/run/omnicube/omnicubeautosnap.sync_pool.lock

EXIT STATUS

0

Normal completion; also returned when another instance already holds the lock and when the run-level guard aborts the run.

1

The lock directory could not be created for a reason other than "already exists" (missing parent, permissions, no space).

2

Usage error: unknown option, missing NAME or an unexpected argument.

78

config/site is not set on the SMF instance, so ${PROPPREFIX} is unknown and utils.sh refuses to continue.

FILES

/opt/omnicube/lib/common/utils.sh

Shared library: logging, locking, run-level guard, get_snap_policy_path().

/var/opt/omnicube/backup/policies/<policy>.conf

Site policy, used when present.

/opt/omnicube/backup/policies/default.conf

Shipped policy, the fallback; see default.conf(5).

/var/run/omnicube/${logtag}.sync_pool.lock

Lock directory, one per SMF instance (${logtag} carries the instance's prefix, so instances run concurrently), under ${LOCK_BASE} (mode 1775, group from config/lock_group).

/etc/nologin

Presence aborts the run (shutdown in progress).

ENVIRONMENT

OC_SMF_INSTANCE

SMF instance whose config/site provides ${PROPPREFIX}; default default. -i overrides it.

OC_IGNORE_RUNLEVEL

When non-empty, bypasses the run-level guard.

SECURITY

Snapshot and property changes use pfexec, so the caller needs the OmniCube RBAC profile (/etc/security/prof_attr.d/omnicube, /etc/security/exec_attr.d/omnicube). Policy files are sourced as bash and run with the caller's privileges: they must be root-owned and not group or world writable.

SEE ALSO

autocleansnap(8), autosync(8), sync_pool.sh(8), default.conf(5), oc_lock(3), oc_policy(3), oc_runlevel(3), omnicube_utils(3), omnicube(7).

NOTES

Snapshot names depend only on the type and the time, so two instances due for the same type in the same minute share one snapshot; the second finds it existing and does nothing. The per-instance is_locked guard does not serialize instances, so a creation that fails because the other instance won the race is not reported as an error.

The type loop covers weekly, daily, hourly and frequent only. The yearly naming rule exists in the code but is unreachable, so autosnap never creates yearly snapshots even with RETENTION[yearly] greater than zero, although autocleansnap(8) does handle the type.

is_locked is set on the top-level zpool, not on the dataset, so snapshotting one dataset briefly blocks OmniCube jobs on every dataset of that pool.

man8/autosnap.8generated 2026-10-08 13:21 CEST