Contents
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
- filetrigger for vlc-plugin cache refresh
- filetrigger for dovecot reload for modules installation/removal
- filetrigger for ibus-table update
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
- either use
- 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:
- current rpm.org implementation
- http://www.rpm.org/wiki/FileTriggers
- http://rpm.org/api/4.4.2.2/triggers.html - new filetriggers are based on regular trigger logic/syntax
- triggers in dpkg:
- older discussion about current rpm.org implementation details:
- Original version of this page in Mandriva wiki, has some details about RPM5 filetrigger implementation
DEPRECATED: details about our old custom filetriggers implementation
commit that dropped our old custom filetriggers implementation