# Debian packaging manual - chapter 6
Package maintainer scripts and installation procedure

## 6.1 Introduction to package maintainer scripts

It is possible supply scripts as part of a package which `dpkg` will run for you when your package is installed, upgraded or removed.

These scripts should be the files `preinst`, `postinst`, `prerm` and `postrm` in the control area of the package. They must be proper exectuable files; if they are scripts (which is recommended) they must start with the usual `#!` convention. They should be readable and executable to anyone, and not world-writeable.

`dpkg` looks at the exit status from these scripts. It is important that they exit with a non-zero status if there is an error, so that `dpkg` can stop its processing. For shell scripts this means that you almost always need to use `set -e` (this is usually true when writing shell scripts, in fact). It is also important, of course, that they don't exit with a non-zero status if everything went well.

It is necessary for the error recovery procedures that the scripts be idempotent: ie, invoking the same script several times in the same situation should do no harm. If the first call failed, or aborted half way through for some reason, the second call should merely do the things that were left undone the first time, if any, and exit with a success status.

When a package is upgraded a combination of the scripts from the old and new packages is called in amongst the other steps of the upgrade procedure. If your scripts are going to be at all complicated you need to be aware of this, and may need to check the arguments to your scripts.

Broadly speaking the `preinst` is called before (a particular version of) a package is installed, and the `postinst` afterwards; the `prerm` before (a version of) a package is removed and the `postrm` afterwards.

Programs called from maintainer scripts should not normally have a path prepended to them. Before installation is started `dpkg` checks to see if the programs `ldconfig`, `start-stop-daemon`, `install-info`, and `update-rc.d` can be found via the `PATH` environment variable. Those programs, and any other program that one would expect to on the `PATH`, should thus be invoked without an absolute pathname. Maintainer scripts should also not reset the `PATH`, though they might choose to modify it by pre- or appending package-specific directories. These considerations really apply to all shell scripts.

## 6.2 Summary of ways maintainer scripts are called

- new-preinst `install`
- new-preinst `install` old-version
- new-preinst `upgrade` old-version
- old-preinst `abort-upgrade` new-version

- postinst `configure` most-recently-configured-version
- old-postinst `abort-upgrade` new version
- conflictor's-postinst `abort-remove` `in-favour` package new-version
- deconfigured's-postinst `abort-deconfigure` `in-favour` failed-install-package version `removing` conflicting-package version

- prerm `remove`
- old-prerm `upgrade` new-version
- new-prerm `failed-upgrade` old-version
- conflictor's-prerm `remove` `in-favour` package new-version
- deconfigured's-prerm `deconfigure` `in-favour` package-being-installed version `removing` conflicting-package version

- postrm `remove`
- postrm `purge`
- old-postrm `upgrade` new-version
- new-postrm `failed-upgrade` old-version
- new-postrm `abort-install`
- new-postrm `abort-install` old-version
- new-postrm `abort-upgrade` old-version
- disappearer's-postrm `disappear` overwriter new-version

## 6.3 Details of unpack phase of installation or upgrade

The procedure on installation/upgrade/overwrite/disappear (ie, when running `dpkg --unpack`, or the unpack stage of `dpkg --install`) is as follows. In each case if an error occurs the actions in are general run backwards - this means that the maintainer scripts are run with different arguments in reverse order. These are the `error unwind' calls listed below.

1. 1. If a version the package is already installed, call

          old-prerm upgrade new-version

   2. If this gives an error (ie, a non-zero exit status), dpkg will attempt instead:

          new-prerm failed-upgrade old-version

      Error unwind, for both the above cases:

          old-postinst abort-upgrade new-version

2. If a `conflicting' package is being removed at the same time:
   1. If any packages depended on that conflicting package and `--auto-deconfigure` is specified, call, for each such package:

          deconfigured's-prerm deconfigure \
              in-favour package-being-installed version \
              removing conflicting-package version

      Error unwind:

          deconfigured's-postinst abort-deconfigure \
              in-favour package-being-installed-but-failed version \
              removing conflicting-package version

      The deconfigured packages are marked as requiring configuration, so that if `--install` is used they will be configured again if possible.

   2. To prepare for removal of the conflicting package, call:

          conflictor's-prerm remove in-favour package new-version

      Error unwind:

          conflictor's-postinst abort-remove \
              in-favour package new-version

3. 1. If the package is being upgraded, call:

          new-preinst upgrade old-version

   2. Otherwise, if the package had some configuration files from a previous version installed (ie, it is in the `configuration files only' state):

          new-preinst install old-version

   3. Otherwise (ie, the package was completely purged):

          new-preinst install

      Error unwind versions, respectively:

          new-postrm abort-upgrade old-version
          new-postrm abort-install old-version
          new-postrm abort-install

4. The new package's files are unpacked, overwriting any that may be on the system already, for example any from the old version of the same package or from another package (backups of the old files are left around, and if anything goes wrong dpkg will attempt to put them back as part of the error unwind).

   It is an error for a package to contains files which are on the system in another package, unless `Replaces` is used (see `Replaces` - overwriting files and replacing packages, section 8.5). Currently the `--force-overwrite` flag is enabled, downgrading it to a warning, but this may not always be the case.

   It is a more serious error for a package to contain a plain file or other kind of nondirectory where another package has a directory (again, unless `Replaces` is used). This error can be overridden if desired using `--force-overwrite-dir`, but this is not advisable.

   Packages which overwrite each other's files produce behaviour which though deterministic is hard for the system administrator to understand. It can easily lead to `missing' programs if, for example, a package is installed which overwrites a file from another package, and is then removed again.[19]

   A directory will never be replaced by a symbolic links to a directory or vice versa; instead, the existing state (symlink or not) will be left alone and `dpkg` will follow the symlink if there is one.

5. 1. If the package is being upgraded, call

          old-postrm upgrade new-version

   2. If this fails, `dpkg` will attempt:

          new-postrm failed-upgrade old-version

      Error unwind, for both cases:

          old-preinst abort-upgrade new-version

   This is the point of no return - if `dpkg` gets this far, it won't back off past this point if an error occurs. This will leave the package in a fairly bad state, which will require a successful reinstallation to clear up, but it's when `dpkg` starts doing things that are irreversible.

6. Any files which were in the old version of the package but not in the new are removed.

7. The new file list replaces the old.

8. The new maintainer scripts replace the old.

9. Any packages all of whose files have been overwritten during the installation, and which aren't required for dependencies, are considered to have been removed. For each such package,
   1. `dpkg` calls:

          disappearer's-postrm disappear \
              overwriter overwriter-version

   2. The package's maintainer scripts are removed.

   3. It is noted in the status database as being in a sane state, namely not installed (any conffiles it may have are ignored, rather than being removed by `dpkg`). Note that disappearing packages do not have their prerm called, because `dpkg` doesn't know in advance that the package is going to vanish.

10. Any files in the package we're unpacking that are also listed in the file lists of other packages are removed from those lists. (This will lobotomise the file list of the `conflicting' package if there is one.)

11. The backup files made during installation, above, are deleted.

12. The new package's status is now sane, and recorded as `unpacked'. Here is another point of no return - if the conflicting package's removal fails we do not unwind the rest of the installation; the conflicting package is left in a half-removed limbo.

13. If there was a conflicting package we go and do the removal actions (described below), starting with the removal of the conflicting package's files (any that are also in the package being installed have already been removed from the conflicting package's file list, and so do not get removed now).

## 6.4 Details of configuration

When we configure a package (this happens with `dpkg --install`, or with `--configure`), we first update the conffiles and then call:

    postinst configure most-recently-configured-version

No attempt is made to unwind after errors during configuration.

If there is no most recently configured version `dpkg` will pass a null argument; older versions of dpkg may pass `<unknown>` (including the angle brackets) in this case. Even older ones do not pass a second argument at all, under any circumstances.

## 6.5 Details of removal and/or configuration purging

1.     prerm remove

2. The package's files are removed (except conffiles).

3.     postrm remove

4. All the maintainer scripts except the postrm are removed.

   If we aren't purging the package we stop here. Note that packages which have no postrm and no conffiles are automatically purged when removed, as there is no difference except for the `dpkg` status.

5. The conffiles and any backup files (`~`-files, `#*#` files, `%`-files, `.dpkg-{old,new,tmp}`, etc.) are removed.

6.     postrm purge

7. The package's file list is removed.

No attempt is made to unwind after errors during removal.

Debian packaging manual - Copyright ©1996 Ian Jackson.
Contents; abstract; next; back.