From Mageia wiki
Jump to: navigation, search

Introduction

Filetriggers are a concept of automagically running specific commands, if specific files have been added or removed to the system when rpm packages are (un)installed.

Typical use cases are:

  • updating /etc/ld.so.cache when some libraries have been added/removed in /usr/lib or /lib
  • running update-menus to update menus of non-XDG compliant desktops when some *.desktop have been added/removed in /usr/share/applications
  • updating icon caches when icons have been added or removed somewhere below /usr/share/icons

Usage

If you only want to use triggers in a package, or want to understand the concept, just read this Usage section.

With rpm 4.13 we have switched to upstream rpm filetriggers As you can see at the bottom of that page there are several types of triggers. We prefer transaction-based triggers, which only run once per package (un)installation transaction.

In general

  • filetriggers will get executed if a file matching the path prefix of the trigger will get installed or uninstalled by any package.
  • Filetriggers will also execute if the package that contains the trigger will itself get installed or updated.


Filetriggers consist of two parts:

  • a tag (%file_trigger_tag) which specifies when this trigger should run, optional options for the trigger, and the mandatory path prefix which specifies the path containing file(s) on which the trigger should activate
  • a script body which specifies commands to run when file(s) below the specified path prefix change


Below is one example of a transaction-based filetrigger to run ldconfig for libraries that are installed/removed.


Example: ldconfig filetrigger (contained in glibc package)

 transfiletriggerin scriptlet (using /bin/sh) -- /lib/, /lib64/

The part on the right side of the -- is the path prefix/filter, specifying to run the following script body on all files in /usr/lib and /usr/lib64 ( keep in mind that since the UsrMove or UsrMigration /lib and /lib64 are only symlinks to /usr/lib and /usr/lib64 )

 grep -F '.so.' | ldconfig -X

This is the script body, which specifies the command to run (ldconfig -X} in this case) on the files specified by filteres list of files. rpm will pass a list of all files below the path prefix specified above to the script body, which can then filter this list (in our example we only want to match all *.so.* files via grep -F '.so.' ) and then pass it to standard input of the command that we want to run.

Example output was queried via rpm -q --filetriggers glibc - the actual trigger in the spec looks like this:

 %transfiletriggerin -P 2000000 -- /lib/ /lib64/
 grep -F '.so.' | ldconfig -X

Example: migration from old implementation to new rpm upstream implementation

See the following commits to easily compare the before/after diffs

Currently supported filetriggers

  • apache reload/restart for changes in /etc/httpd/conf/{modules.d,conf.d,sites.d,webapps.d}/
  • fc-cache
  • gconf-schemas.filter
  • gio-querymodules
  • glib-compile-schemas
  • gtk-icon-cache-gnome-{gnome,hicolor,oxygen}
  • install-info
  • ldconfig
  • man-db
  • mime-database
  • nspluginwrapper
  • python .pyo
  • systemd reload for changes in /etc/init.d or /lib/systemd/system/
  • tetex
  • update-desktop-database
  • update-menus
  • vlc-plugins

commands to query filetriggers

As the new upstream filetriggers are not file-based, we cannot query all filetriggers as before via e.g. urpmf /var/lib/rpm/filetriggers

To show an overview of the triggers of all currently installed packages, use

 rpm -qa --filetriggers |grep -E "trigger[i,p,u]"

Simply omit the grep -E "trigger[i,p,u]" part to also see the script body.


To show the triggers of a package that is not yet installed

 rpm -qp /path/to/package.rpm --filetriggers

Some more details including the package name to which a trigger belongs can be obtained via e.g.

 rpm -qa --qf "%{NAME} %{TRANSFILETRIGGERTYPE} %{TRANSFILETRIGGERNAME} %{TRANSFILETRIGGERCONDS} %{TRANSFILETRIGGERFLAGS} %{TRANSFILETRIGGERINDEX} %{TRANSFILETRIGGERPRIORITIES} %{TRANSFILETRIGGERSCRIPTPROG} %{TRANSFILETRIGGERSCRIPTFLAGS}\n" | grep -v '(none) (none) (none) (none) (none) (none) (none) (none)'

All tags related to filetriggers can be queried via

 rpm --querytags|grep -i filetrigger


Implementation details

Since rpm 4.13 we have switched to upstream rpm filetriggers Sadly there doesn't seem to be much user-facing documentation on the internal implementation available apart from the source code.

Limitations / caveats

  • by default filetriggers will be added to the main package if they are listed anywhere between %install and the bottom of the .spec
    • either use %file_trigger_tag -n subpackagename to specify the subpackage - see glib2.0 commit for an example
    • or put the trigger directly below the preamble section for the subpackage
  • path prefix does only support literal path definition(s) and no regular expressions
    • if trigger should only run on specific files below that path prefix, file list needs to be filtered in script body, see the example on ldconfig
  • filetriggers script body greedily consumes everything up to the next section in the spec
    • e.g. if you put it in the middle of %install section it will consume any following shell command, this also applies to macros like %find_lang - for an example about this see this commit on our null package
    • best put it directly above the following section, so at end of %install directly before %files or %post

External links

Some links about filetriggers:

DEPRECATED: details about our old custom filetriggers implementation

commit that dropped our old custom filetriggers implementation