Safely Test and Activate dpkg Package Triggers

You will finish with a safe way to check trigger support with dpkg-trigger and test an activation without touching the dpkg database. You will also learn when a real activation is appropriate. The examples use dpkg-trigger 1.22.6 from dpkg package version 1.22.6ubuntu6.6 on this machine. Allow about ten minutes. Most checks need no elevated privileges, but a real activation is package-management work and normally belongs in a maintainer script or a carefully controlled administrative session.

A trigger records that an event matters to one or more interested packages. dpkg normally processes the interested packages later, often at the end of a package operation. dpkg-trigger records the request; it does not run the interested package's trigger handlers itself.

1. Confirm that this dpkg supports triggers

Start with the built-in support check:

$ dpkg-trigger --check-supported
$ printf 'exit status: %s\n' "$?"
exit status: 0

The command is quiet when support is present and returns status 0. A status of 1 means the running dpkg is not trigger-capable, with an explanation sent to standard error. A status of 2 means a fatal usage or system error. This check does not activate a trigger and does not need sudo.

Checkpoint: if your script only needs to know whether the feature exists, stop here. The manual recommends activating the desired trigger directly rather than treating this check as a substitute for the operation.

2. Test a trigger name without changing state

Use --no-act while developing a maintainer-script command or checking an explicit trigger name. Supply --by-package to identify the package that would be treated as the trigger awaiter:

$ dpkg-trigger --no-act --by-package=dpkg example-trigger
$ printf 'exit status: %s\n' "$?"
exit status: 0

example-trigger is only a harmless, syntactically valid test name. It is not a trigger that another installed package is expected to handle. With --no-act, the command checks the request without actually changing anything.

The trigger name is one argument, with no whitespace. Explicit trigger names use package-name-like syntax, while file triggers have their own recognised forms. Do not invent a name for a production command: use the interface documented by the package that declares interest in it.

Do not be distracted by the default caller check. Without --by-package, an administrator running the command interactively normally receives an error saying that it must be called from a maintainer script or with that option. A maintainer script normally supplies DPKG_MAINTSCRIPT_PACKAGE automatically. For an interactive test, an explicit --by-package=PACKAGE makes the caller identity clear.

3. Choose how the triggering package waits

The default is --await. If an interested package accepts the trigger, the triggering package can remain marked as awaiting its processing. That protects the normal package-operation ordering, but it can leave package status temporarily short of fully installed until dpkg processes the trigger.

Use --no-await when the caller must not wait for interested packages. The interested packages still receive the pending trigger, but the caller's status is not changed to await them:

$ dpkg-trigger --no-act --by-package=dpkg --no-await example-trigger
$ printf 'exit status: %s\n' "$?"
exit status: 0

Use --await when waiting is the intended package contract:

$ dpkg-trigger --no-act --by-package=dpkg --await example-trigger
$ printf 'exit status: %s\n' "$?"
exit status: 0

An interested package declaring a noawait relationship can prevent --await from having an effect. Treat that as package metadata, not as a switch that forces another package to run immediately.

4. Activate a real trigger only when the package contract requires it

Remove --no-act only after you have confirmed the exact trigger name, caller package and wait policy. This is the state-changing form:

$ sudo dpkg-trigger --by-package=PACKAGE_NAME --no-await TRIGGER_NAME

Replace both uppercase values with real values documented by the package. The command may need access to /var/lib/dpkg, and an ordinary user may therefore need elevated privileges. Do not run this example with guessed values on a production host. Activating an unknown trigger can create pending work for packages that happen to declare interest, and repeated activation is not a way to force immediate processing.

There is no inverse command that retracts a trigger activation. If you activate the wrong name, let the relevant package-management workflow process it, then investigate the package state. Do not edit files under /var/lib/dpkg by hand. For a test that must leave no package metadata behind, return to the --no-act examples instead.

5. Use a different dpkg root only for a deliberate alternate database

--root=DIRECTORY changes the filesystem root and, since dpkg 1.21.0, uses DIRECTORY/var/lib/dpkg as the administrative directory. --admindir=DIRECTORY selects the database directly. These options are useful for a deliberately prepared image or test root, not as a workaround for a broken live database.

$ dpkg-trigger --no-act --root=/srv/image --by-package=dpkg example-trigger
$ printf 'exit status: %s\n' "$?"
exit status: 0

The test above does not require that the alternate root contain a complete usable installation because no state is written. A real activation against an incomplete or wrong root can be confusing and may damage the image's package bookkeeping. Check the target path before removing --no-act.

6. Diagnose failures by status, not by guesswork

Capture the status immediately, before another command overwrites it:

dpkg-trigger --no-act --by-package=dpkg TRIGGER_NAME
status=$?
case "$status" in
    0) printf '%s\n' 'trigger request accepted for testing' ;;
    1) printf '%s\n' 'check or assertion returned false' >&2 ;;
    2) printf '%s\n' 'fatal usage or dpkg database error' >&2 ;;
esac
exit "$status"

Status 1 is the documented false result for a check or assertion command. Status 2 covers invalid command-line use and unrecoverable system interactions. A common status-2 mistake is passing a trigger name containing whitespace, or omitting the caller identity when running outside a maintainer script.

For a failed real activation, first rerun the exact request with --no-act. Check the package name, trigger spelling and selected root or administrative directory. Then inspect package state with your normal dpkg tools. Do not retry blindly with sudo; privilege does not repair a wrong trigger contract.

Done means