[ previous ] [ Contents ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ A ] [ B ] [ C ] [ D ] [ E ] [ F ] [ G ] [ next ]
It is possible to supply scripts as part of a package which the package management system will run for you when your package is installed, upgraded or removed.
These scripts are the files preinst
, postinst
,
prerm
and postrm
in the control area of the package.
They must be proper executable files; if they are scripts (which is
recommended), they must start with the usual #! convention. They
should be readable and executable by anyone, and must not be world-writable.
The package management system 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 the package management system 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 exit with a zero status if everything went well.
Additionally, packages interacting with users using debconf in the
postinst
script should install a config
script in the
control area, see Prompting in
maintainer scripts, Section 3.9.1 for details.
When a package is upgraded a combination of the scripts from the old and new packages is called during 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, the package management
system 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 be in
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 prepending or appending package-specific
directories. These considerations really apply to all shell scripts.
It is necessary for the error recovery procedures that the scripts be idempotent. This means that if it is run successfully, and then it is called again, it doesn't bomb out or cause any harm, but just ensures that everything is the way it ought to be. 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 if everything is OK.[45]
The maintainer scripts are guaranteed to run with a controlling terminal and can interact with the user. Because these scripts may be executed with standard output redirected into a pipe for logging purposes, Perl scripts should set unbuffered output by setting $|=1 so that the output is printed immediately rather than being buffered.
Each script must return a zero exit status for success, or a nonzero one for failure, since the package management system looks for the exit status of these scripts and determines what action to take next based on that datum.
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
postinst abort-remove
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 overwriter-version
The procedure on installation/upgrade/overwrite/disappear (i.e., when running dpkg --unpack, or the unpack stage of dpkg --install) is as follows. In each case, if a major error occurs (unless listed below) the actions are, in 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.
If a version of the package is already installed, call
old-prerm upgrade new-version
If the script runs but exits with a non-zero exit status, dpkg
will attempt:
new-prerm failed-upgrade old-version
If this works, the upgrade continues. If this does not work, the error unwind:
old-postinst abort-upgrade new-version
If this works, then the old-version is "Installed", if not, the old version is in a "Failed-Config" state.
If a "conflicting" package is being removed at the same time, or if any package will be broken (due to Breaks):
If --auto-deconfigure is specified, call, for each package to be deconfigured due to Breaks:
deconfigured's-prerm deconfigure \ in-favour package-being-installed version
Error unwind:
deconfigured's-postinst abort-deconfigure \ in-favour package-being-installed-but-failed version
The deconfigured packages are marked as requiring configuration, so that if --install is used they will be configured again if possible.
If any packages depended on a conflicting package being removed 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.
To prepare for removal of each conflicting package, call:
conflictor's-prerm remove \ in-favour package new-version
Error unwind:
conflictor's-postinst abort-remove \ in-favour package new-version
If the package is being upgraded, call:
new-preinst upgrade old-version
If this fails, we call:
new-postrm abort-upgrade old-version
If that works, then
old-postinst abort-upgrade new-version
is called. If this works, then the old version is in an "Installed" state, or else it is left in an "Unpacked" state.
If it fails, then the old version is left in an "Half-Installed" state.
Otherwise, if the package had some configuration files from a previous version installed (i.e., it is in the "configuration files only" state):
new-preinst install old-version
Error unwind:
new-postrm abort-install old-version
If this fails, the package is left in a "Half-Installed" state, which requires a reinstall. If it works, the packages is left in a "Config Files" state.
Otherwise (i.e., the package was completely purged):
new-preinst install
Error unwind:
new-postrm abort-install
If the error-unwind fails, the package is in a "Half Installed" phase, and requires a reinstall. If the error unwind works, the package is in a not installed state.
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 kept temporarily, and if anything goes wrong the package management system will attempt to put them back as part of the error unwind.
It is an error for a package to contain files which are on the system in another package, unless Replaces is used (see Overwriting files and replacing packages - Replaces, Section 7.6).
It is a more serious error for a package to contain a plain file or other kind of non-directory 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 behavior 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.[46]
A directory will never be replaced by a symbolic link 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.
If the package is being upgraded, call
old-postrm upgrade new-version
If this fails, dpkg
will attempt:
new-postrm failed-upgrade old-version
If this works, installation continues. If not, Error unwind:
old-preinst abort-upgrade new-version
If this fails, the old version is left in an "Half Installed" state. If it works, dpkg now calls:
new-postrm abort-upgrade old-version
If this fails, the old version is left in an "Half Installed" state. If it works, dpkg now calls:
old-postinst abort-upgrade new-version
If this fails, the old version is in an "Unpacked" state.
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 re-installation to clear up,
but it's when dpkg
starts doing things that are irreversible.
Any files which were in the old version of the package but not in the new are removed.
The new file list replaces the old.
The new maintainer scripts replace the old.
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
dpkg
calls:
disappearer's-postrm disappear \ overwriter overwriter-version
The package's maintainer scripts are removed.
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.
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 lobotomize the file list of the "conflicting" package if there is one.)
The backup files made during installation, above, are deleted.
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.
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).
When we configure a package (this happens with dpkg --install and dpkg --configure), we first update any conffiles and then call:
postinst configure most-recently-configured-version
No attempt is made to unwind after errors during configuration. If the configuration fails, the package is in a "Failed Config" state, and an error message is generated.
If there is no most recently configured version dpkg
will pass a
null argument. [47]
prerm remove
If prerm fails during replacement due to conflict
conflictor's-postinst abort-remove \ in-favour package new-version
Or else we call:
postinst abort-remove
If this fails, the package is in a "Failed-Config" state, or else it remains "Installed".
The package's files are removed (except conffiles).
postrm remove
If it fails, there's no error unwind, and the package is in an "Half-Installed" state.
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.
The conffiles and any backup files (~-files, #*# files, %-files, .dpkg-{old,new,tmp}, etc.) are removed.
postrm purge
If this fails, the package remains in a "Config-Files" state.
The package's file list is removed.
[ previous ] [ Contents ] [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] [ 11 ] [ 12 ] [ A ] [ B ] [ C ] [ D ] [ E ] [ F ] [ G ] [ next ]
Ubuntu Policy Manual
version 3.8.2.0ubuntu3, 2017-02-20