wiki:MaintainerScripts

About maintainer scripts

(This is an abbreviated overview. The full documentation is available  here.)

Maintainer scripts are, as the name implies, scripts created by the maintainer of a Debian package to aid in its installation, removable or upgrade. Specifically, there are often times when merely installing some files is not sufficient, and action must be taken upon successful installation (rebuilding a cache, etc). Most common operations (e.g., ldconfig) are automatic, but for cases when you need to specify custom actions, you would use maintainer scripts.

Maintainer scripts must be  idempotent, in that running them multiple times must not produce different results.

Maintainer scripts must exit with status 0 upon successful completion, or any non-zero status otherwise. For this reason, most maintainer scripts use set -e at the beginning of the script, which causes Bash to error out if any command returns non-zero status. You can combine this with an or (||) clause to catch non-fatal errors. e.g.

command-which-might-fail || true

Names

Each package can have up to 4 maintainer scripts, which are placed in the debian/ directory when building the package. Like all debhelper files, they can be prepended with the package's name (e.g. package1.postinst).

  • postinst:The package’s postinst maintainer script.
  • preinst:The package’s postinst maintainer script.
  • postrm:The package’s postinst maintainer script.
  • prerm:The package’s postinst maintainer script.

All scripts should include the tag #DEBHELPER# as the penultimate line(1) of the script, should explicitly exit with status 0 at the end of the script, and should handle all possible arguments (see below). When creating new maintainer scripts, you should use the examples in /usr/share/debhelper/dh_make/debian/. In there, you'll fine postinst.ex, preinst.ex, etc.

(1) There may be times when you want #DEBHELPER# at the top of the script. Basically, #DEBHELPER# will be replaced by all the other stuff added by debhelper scripts. So if you supply a _packagename_.init script, dh_installinit will add some code to restart the daemon, and that code will show up where the #DEBHELPER# tag is. This does require a bit of thought. If you're using ConfigPackageDev and diverting a file, and then relying on the file already being diverted in the postinst, then the tag needs to go at the top.

Arguments

Each of the maintainer scripts can be called with a number of arguments that indicate what particular dpkg operation is going on. Your script must be able to handle all possible arguments, and error out with unrecognized ones. (Again, the examples described above do this for you already). In most cases, however, you'll only handle one or two of the arguments. Each of the examples in /usr/share/debhelper/dh_make/debian/ contains a comment block at the top indicating all possible invocations.

User Interaction

You don't necessarily get a controlling terminal in maintainer scripts, and thus can't interact directly with the user using normal shell scripting techniques. However, a log of maintainer script output is stored, and you should feel free to be verbose with error messages. Because maintainer scripts which use set -e will error out immediately upon a command failure, it's best to clearly comment your code and/or catch some obscure errors and print more info to the terminal.

Example: command-which-might-fail || echo "Couldn't rebuild cache, see /var/log/something" && exit 1

If you do need to interact with the user, you'll want to use Debconf.

TODO: Document Debconf usage

Testing

When testing new packages, it's important to test both clean installs _and_ upgrades from previous versions. It's possible to make a mistake such that installs work, but not upgrades (or vice versa). This requires a lot of cleanup and can inconvenience many users.