Using the snapctl tool

The snapctl tool is bundled with snapd to provide specific environmental feedback and a limited set of controls from within the context of a snap’s execution environment in relation to snapd. It can be used, for example, to retrieve and set snap configuration options, check the status of a running snap, and reboot an Ubuntu Core 20 environment.

snapctl is typically run from a script within a snap, rather than on the host system. These scripts are used by snap developers to implement hooks, or from within snapcraft.yaml, to augment a snap’s execution environment.

For details on using snapctl to add user options to a snap, see Adding snap configuration and see Creating a snap for an overview of the snap development process.

From within a snap, snapctl can do the following:


Configuration options

A snap’s configuration options can be queried and altered with the snapctl get, snapctl set and snapctl unset commands. These work very similar to the analogous snap get/set/.. commands outside the snap. The main difference is that using these commands from within a snap will not trigger the configure hook.

The snapctl command uses the same get, set and unset syntax as the snap command:

snapctl get <configuration option>

For example, the following sets a value of 80 for http:

snapctl set ports.http=80

To unset a value, pass its name with snapctl unset, and more than one value can be passed at a time:

snapctl unset ports.http ports.https

For convenience, an option can also be unset by adding an exclamation mark (!) to the end of a value. For example, the following unsets https:

snapctl set ports.http=80 ports.https!

By using a dot in the key of an option, you create a nested configuration. You can retrieve multiple nested options by specifying their common key:

$ snapctl get ports
{
"http": "80",
"https": "443"
}

To see this in action, look at the NextCloud snap. It uses snapctl within its various hooks to set configuration options such as snapctl get private.mode and snapctl set private.mode="$1".

For more information, see Adding snap configuration and The configure hook.

Health state

:information_source: Health reporting is under development and its capabilities and syntax may change.

Snap developers can use snapctl set-health to provide feedback on the operational state, or health, of a snap.

It uses the following syntax:

snapctl set-health [--code=<error code>] <status> [<message>]

status can be one of the following:

  • okay: which takes no message and no code
  • waiting: some resource the snap needs isn’t ready yet, and there’s nothing for the user to do but wait. A message (+code) must explain what it’s waiting for
  • blocked: the user needs to do something for the snap to do something. A message (+code) must say what
  • error: something went wrong; a message (+code) must explain what has broken

Outside the snap, health status in included as a note in the output to snap list, and as a category in snap info for a specific snap:

$ snap info nextcloud
name:    nextcloud
summary: Nextcloud Server - A safe home for all your data
health:
  status:  blocked
  message: Backing up database.
  checked: today at 10:44 GMT

For more comprehensive information on using snapctl set-health, see Health checks.

Interface connections

(from snapd 2.43+)

The state of a specific snap interface can be probed with the snapctl is-connected sub-command by supplying either a slot or plug name as an argument:

snapctl is-connected <plug|slot>

The plug or slot is always the name of the plug/slot from the calling snap.

If the given plug or slot is connected, the command returns the standard exit code for success, which is 0 on POSIX systems. A non-zero exit code is returned in all other cases.

For example, the following indicates the camera interface is not connected:

$ snapctl is-connected camera; echo $?
1

This behaviour can be easily used within a hook, for example:

if snapctl is-connected camera; then
  # exit status=0. logic when connected
  echo "connected"
else
  # logic when not connected; note if this is run from hooks.
  # printing to stdout/stderr is not visible to the user
  # (unless the hook fails entirely with exit status > 0)
  echo "not connected"
fi

Snaps can only query their own plugs and slots because the snap name is implicit and implied by the snapctl execution context.

See Snapcraft interfaces for more details on manipulating interfaces from a snap.

Model information

(from snapd 2.56+ onwards)

A model assertion contains the fundamental definition of a snap-based device, such as a device running Ubuntu Core.

The snap model command can be used to return to the active model identification for the device, and snapctl model returns the equivalent to snap model --verbose from within a snap. However, for this to work, the requesting snap needs to meet one of the following criteria:

The requesting snap must be either:

  1. a gadget snap
  2. published from the same brand as the device model assertion
  3. have the snapd-control plug

By default, the output model identification information is presented in a structured yaml-like format:

brand-id:      canonical
model:         ubuntu-core-22-amd64
grade:         signed
[...]

This can be changed to JSON with the --json flag:

{
  "architecture": "amd64",
  "base": "core22",
  "brand-id": "canonical",
  "grade": "signed",
  "model": "ubuntu-core-22-amd64",
  "serial": "5f1ee168-ee21-4c38-b03c-5ff9bef64c1e",
  "snaps": [
    {
      "default-channel": "22/stable",
      "id": "UqFziVZDHLSyO3TqSWgNBoAdHbLI4dAH",
      "name": "pc",
      "type": "gadget"
    },
    [...]

The raw assertion can also be requested with the --assertion flag.

Mount control

When the mount-control interface is connected, a snapped application or service can use the mount command to mount transient (non-persistent) and persistent filesystem mount points:

snapctl mount -o <options> -t <fstype> </path/to/device> </target/mount/point>

To mount a persistent mount point, add the --persistent option:

$ snapctl mount --persistent -o bind,rw /usr/share /media/mount

A corresponding umount command can be used to remove a mount point:

snapctl umount </path/to/mount/point>

See mount-control interface for further details on permitted filesystems and mount options.

Reboot control (from the UC20+ install-device hook)

The snapctl reboot command can be used to control reboot behaviour from the gadget install-device hook during UC20+ install mode.

See the UC20+ installation process documentation for further details.

Refresh control (from the UC20+ gate-auto-refresh hook)

The gate-auto-refresh hook is executed by snapd for every snap that will be updated with the next automatic refresh. It’s also executed for every snap that is dependent on a snap that will be updated.

This hook is capable of executing the snapctl refresh command with 3 specific arguments, hold, proceed and pending:

This feature is currently considered experimental. See Refresh control for further details.

snapctl refresh --hold

Requests that snapd does not refresh the calling snap, nor the snaps it depends upon, during the current automatic refresh. A snap can hold its own refresh for up to 90 days and other snaps for up to 48 hours. The command prints an error and returns a non-zero exit status if these deadlines are reached and the refresh can no longer be held.

snapctl refresh --proceed

Signals to snapd that a refresh can proceed for both the calling snap and the snaps it depends upon. This does not necessarily mean the update will happen, because they may be held by other snaps, and snapd only proceeds with auto-refresh after consulting gate-auto-refresh hooks of all potentially affected snaps.

snapctl refresh --pending

Checks whether the executing snap has a pending refresh, or will be affected by the refresh of its base snap.

The output from snapctl refresh --pending includes the following details:

  • pending: none, inhibited or ready
  • channel: tracking-channel
  • version: version (only if there is a pending refresh for the snap itself)
  • revision: revision (only if there is a pending refresh for the snap itself)
  • base: true or false (true if the snap is affected by refresh of its base snap)
  • restart: true or false (true if refresh will cause system restart)

The pending output value is set to “none” if there is no pending refresh for the snap and the value is “ready” if there is a pending refresh. A pending value of “inhibited” indicates that the next refresh is inhibited because one or more of the snap’s applications are running. This currently requires the experimental refresh app awareness feature to be enabled (see below).

The snap-refresh-control interface

The snapctl refresh --proceed command can be executed by a snapped application outside of the gate-auto-refresh hook if the snap has the snap-refresh-control interface and the interface is connected. This enables the snap to trigger an auto-refresh outside of the normal auto-refresh schedule and should be used cautiously.

Please note that the “snapctl refresh” commands cannot be used from hooks other than gate-auto-refresh hook.

If the gate-auto-refresh hook doesn’t invoke “snapctl refresh --proceed” or “snapctl refresh --hold” commands and exits with exit code 0, the refresh proceeds normally as if the hook didn’t exist (except for respecting “inhibited” status if refresh app awareness is in use).

If the hook fails with an error, snapd assumes “hold” as long as the maximum deadline hasn’t been reached.

Services

As with configuration options (see above), snapctl sub-commands for managing services are the same as those used by the snap command. See Services and daemons for further details.

To query the startup and running state of a service, for example, use snapctl services <service-name>:

$ snapctl services nextcloud.mysql
Service          Startup  Current  Notes
nextcloud.mysql  enabled  active   -

The start, stop and restart snapctl commands can be used to start, stop and restart services:

$ snapctl stop nextcloud.mysql
$ snapctl services nextcloud.mysql
Service          Startup  Current   Notes
nextcloud.mysql  enabled  inactive  -

Services can be enabled and disabled by adding the --enable argument to snapctl start and --disable to snapctl stop respectively:

$ snapctl start nextcloud.myql --enable
$ snapctl stop nextcloud.mysql --disable

Snaps can only query their own services.

System mode

The snapctl system-mode command returns YAML-formatted details about specific system states:

$ snapctl system-mode
system-mode: install
seed-loaded: true
factory: true

The following keys and values can potentially be returned:

  • system-mode: install, factory-reset, recover, run
    The current (operational) system mode:

    • install: denotes the system is installing
    • factory-reset: a factory reset has been triggered
    • recover: the system is in recovery mode
    • run: indicates the system has booted normally.
      This is the only reported system mode on UC16/UC18 system.

    See Recovery modes for more details on each mode.

  • seed-loaded: true
    Set when the installation of seeded snaps for the model has finished.

  • factory: true
    Only possible on a UC20+ system in install mode (system-mode: install) with the factory image hint set. This value can be used to govern whether factory-only resources may be available. See Factory image hint for more details.

1 Like

This has the wrong link

Which permissions? Snaps should always be able to manage their own services with snapctl, I don’t think there’s any special permissions to enable snapctl stop, etc.

Could you also add a bit about disabling and enabling with the --disable and --enable flags too? I think that’s a common thing to want to do, and just grepping this page for disable reveals nothing.

Thanks for taking a look at this!

fixed, thanks.

ok, thanks for letting me know. I’d wrongly assumed that services that weren’t enabled couldn’t be started from snapctl without permissions, eg. nextcloud.apache. I might try and write more about this to make it easier to understand.

Will do - thanks again!

1 Like

Note: This page misses information about getting and setting interface attributes: https://snapcraft.io/docs/interface-hooks

It would also be useful if the list of functions at the top of the page linked to the different headers, and maybe also show the subcommands for each section.

Thanks for all the updates, and for the interface-hooks suggestion - I’ll add these. I’ve also added links to the subcommand sections. Thanks!

1 Like

The exit code will always be from the pipe operation, not from the is-connected command. Should be:

$ snapctl is-connected camera; echo $?
1

Full credit to @jamesh, see Snapctl is-connected command not working

1 Like

Thanks for letting us know - and good spot. I’ve updated the doc.

1 Like

“check the status [or] a running snap” (para 1)

“snaptctl”

“use [the] snapctl service[s] :”

“gate-auto-refresh-hook” -> “gate-auto-refresh hook” (remove final hyphen)

Fantastic finds, thank so much!

One of my comment lines was unclear; in the “Services” section:

“To query the startup and running state of a service, for example, use snapctl service :”

Should be “snapctl services”, not “snapctl service”.

Thanks, I should have spotted that myself!

@degville

Introduced in 2.57:

Addendum to snapctl system-mode.

system-mode can now also return system-mode: factory-reset on UC20+ devices .

Introduced in 2.56:

snapctl model

The model command returns the active model assertion information for the current device. The command acts in a similar matter to snap model --verbose.

By default, the model identification information is presented in a structured, yaml-like format, but this can be changed to json by using the --json flag. The raw assertion can also be requested with the --assertion flag.

For instance, the following command

snapctl model

could return the following output (minimized example), structured like yaml:

brand-id:      canonical
model:         pc-model
serial:        -- (device not registered yet)
architecture:  amd64
base:          core18
gadget:        pc
kernel:        pc-kernel
timestamp:     2022-01-05T08:25:56Z
1 Like

There’s a typo here, it should read:

factory-reset: a factory reset has been triggered

CC @degville

Ugh, I’m terrible - thanks Zyga!

1 Like

Hi,

I was asking about the permissions required to run snapctl model, and thought it would make sense to cross post here in case it’s just not fully documented.

Cheers, Just

Hi

See: https://github.com/snapcore/snapd/master/overlord/hookstate/ctlcmd/model.go#L153-L176

The model is owned by brand store and protected accordingly which is why the model command requires one of the following permissions criteria should be met:

  1. The requesting snap must be a gadget OR
  2. Come from the same brand as the device model assertion OR
  3. Have the snapd-control plug

→ I have requested for the documentation to be improved.

Thanks for the update and the added information! I’ve now added the permissions criteria to our documentation.

@degville this link 404’s

Thank you so much! Now fixed.

1 Like