[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: How to fix a broken postrm in upcoming releases



On Fri, May 15, 1998 at 02:20:45PM +0100, I wrote:
> I posted some skeleton p{re,ost}{inst,rm} scripts to debian-mentors (or
> was it debian-doc?) a few weeks ago; I'll post them again if you like.
> I think they do a pretty good job of outlining all the possibilities you
> can code for, but in a more easily digestible form than the packaging
> manual's description.

Okay, I've been asked for them.  I have made some updates since last
they were posted...

----------------------------------------------------------------------
Note that most of the activities of your maintainer scripts need not
be conditionalised on the script's parameters.  You probably won't need
these skeleton scripts unless you're doing something tricky.

Some general points relevant to writing all maintainer scripts:

- Trap all errors.
- Don't generate any unnecessary output.
- Return an exit status of zero if you succeed, non-zero if you fail.
- Be idempotent: make sure nothing bad will happen if the script is
  called twice where it would usually be called once.
- Remember the standard input and output may be redirected (e.g. into
  pipes) for logging purposes.

Prompting should whenever possible be confined to the case when the
postinst script is called with the argument "configure":

- If you have a vitally important message to show the system administrator
  (NOT the end user) the postinst should display it, then wait for return
  to be pressed.
- Prompt the user only for the minimum possible information.
- Never prompt for the same information twice, unless the information
  has been purged since last collected.
- If you prompt for a password, do full-screen interaction, or the like,
  use /dev/tty for these things, not standard input/output.

The POSIX shell `:' command is used in the skeleton scripts to comment
out example commands which are only needed in some packages, and to
indicate where your commands could go.

Generally, try to confine most activities to the postinst and prerm
scripts.  Be careful if you put anything unusual in the preinst or postrm,
because the package's dependencies may not be installed when they are run.

Lastly, note that, in dpkg-speak, an 'upgrade' may be to any version of
the same package, even the same version or a previous version.  Thus,
the 'upgrade' cases of the scripts are used even when reinstalling a
package over the top of the same version of itself, or when downgrading.

----------------------------------------------------------------------
#! /bin/sh
# preinst.skeleton
# Skeleton maintainer script showing all the possible cases.
# Written by Charles Briscoe-Smith, March-June 1998.  Public Domain.

# Abort if any command returns an error value
set -e

# This script is called before this version of this package is installed.
# When this script is called, the package's files have not been unpacked
# yet.

case "$1" in
  install)
    # About to install this package.
    :

    # Add a diversion.  This is one of the few things which may be done
    # before installing any files from the package.
    : dpkg-divert --package foo --add --rename \
    :             --divert /usr/bin/other.real /usr/bin/other

    # There are two sub-cases:
    if test "${2+set}" = set; then
      # The configuration files from version $2 of this package are
      # still on the system.
      :

    else
      # There is no existing configuration; install from scratch.
      :

    fi ;;
  upgrade)
    # About to upgrade this package from version $2 TO THIS VERSION.
    # "prerm upgrade" has already been called for the old version of
    # this package.
    :

    ;;
  abort-upgrade)
    # Back out of an attempt to upgrade this package FROM THIS VERSION to
    # version $2.  Undo the effects of "postrm upgrade $2".
    :

    ;;
  *) echo "$0: didn't understand being called with \`$1'" 1>&2
     exit 0;;
esac

exit 0
----------------------------------------------------------------------
#! /bin/sh
# postinst.skeleton
# Skeleton maintainer script showing all the possible cases.
# Written by Charles Briscoe-Smith, March-June 1998.  Public Domain.

# Abort if any command returns an error value
set -e

# This script is called as the last step of the installation of the
# package.  All the package's files are in place, dpkg has already done
# its automatic conffile handling, and all the packages we depend of
# are already fully installed and configured.

# The following idempotent stuff doesn't generally need protecting
# against being run in the abort-* cases.

# Install info files into the dir file
: install-info --quiet --section "section pattern" "Section Title" \
:              --description="Name of the document" /usr/info/foo.info

# Create stub directories under /usr/local
: if test ! -d /usr/local/lib/foo; then
:   if test ! -d /usr/local/lib; then
:     if mkdir /usr/local/lib; then
:       chown root.staff /usr/local/lib || true
:       chmod 2775 /usr/local/lib || true
:     fi
:   fi
:   if mkdir /usr/local/lib/foo; then
:     chown root.staff /usr/local/lib/foo || true
:     chmod 2775 /usr/local/lib/foo || true
:   fi
: fi

# Ensure the menu system is updated
: [ ! -x /usr/bin/update-menus ] || /usr/bin/update-menus

# Arrange for a daemon to be started at system boot time
: update-rc.d foo default >/dev/null

case "$1" in
  configure)
    # Configure this package.  If the package must prompt the user for
    # information, do it here.
    :

    # Activate menu-methods script
    : chmod a+x /etc/menu-methods/foo

    # Update ld.so cache
    : ldconfig

    # Make our version of a program available
    : update-alternatives \
    :       --install /usr/bin/program program /usr/bin/alternative 50 \
    :       --slave /usr/man/man1/program.1.gz program.1.gz \
    :               /usr/man/man1/alternative.1.gz

    # There are three sub-cases:
    if test "${2+set}" != set; then
      # We're being installed by an ancient dpkg which doesn't remember
      # which version was most recently configured, or even whether
      # there is a most recently configured version.
      :

    elif test -z "$2" -o "$2" = "<unknown>"; then
      # The package has not ever been configured on this system, or was
      # purged since it was last configured.
      :

    else
      # Version $2 is the most recently configured version of this
      # package.
      :

    fi ;;
  abort-upgrade)
    # Back out of an attempt to upgrade this package FROM THIS VERSION
    # to version $2.  Undo the effects of "prerm upgrade $2".
    :

    ;;
  abort-remove)
    if test "$2" != in-favour; then
      echo "$0: undocumented call to \`postinst $*'" 1>&2
      exit 0
    fi
    # Back out of an attempt to remove this package, which was due to
    # a conflict with package $3 (version $4).  Undo the effects of
    # "prerm remove in-favour $3 $4".
    :

    ;;
  abort-deconfigure)
    if test "$2" != in-favour -o "$5" != removing; then
      echo "$0: undocumented call to \`postinst $*'" 1>&2
      exit 0
    fi
    # Back out of an attempt to deconfigure this package, which was
    # due to package $6 (version $7) which we depend on being removed
    # to make way for package $3 (version $4).  Undo the effects of
    # "prerm deconfigure in-favour $3 $4 removing $6 $7".
    :

    ;;
  *) echo "$0: didn't understand being called with \`$1'" 1>&2
     exit 0;;
esac

exit 0
----------------------------------------------------------------------
#! /bin/sh
# prerm.skeleton
# Skeleton maintainer script showing all the possible cases.
# Written by Charles Briscoe-Smith, March-June 1998.  Public Domain.

# Abort if any command returns an error value
set -e

# This script is called as the first step in removing the package from
# the system.  This includes cases where the user explicitly asked for
# the package to be removed, upgrade, automatic removal due to conflicts,
# and deconfiguration due to temporary removal of a depended-on package.

# Info files should be uninstalled from the dir file in any case.
: install-info --quiet --remove /usr/info/foo.info

case "$1" in
  remove)
    # This package about to be removed.
    :

    # Remove package-specific directories from /usr/local.  Don't try
    # to remove standard directories such as /usr/local/lib.
    : if test -d /usr/local/lib/foo; then
    :   rmdir /usr/local/lib/foo || true
    : fi

    # Deactivate menu-methods script.
    : chmod a-x /etc/menu-methods/foo

    # Withdraw our version of a program.
    : update-alternatives --remove program /usr/bin/alternative

    # There are two sub-cases:
    if test "${2+set}" = set; then
      if test "$2" != in-favour; then
        echo "$0: undocumented call to \`prerm $*'" 1>&2
        exit 0
      fi
      # We are being removed because of a conflict with package $3
      # (version $4), which is now being installed.
      :

    else
      # The package is being removed in its own right.
      :

    fi ;;
  deconfigure)
    if test "$2" != in-favour -o "$5" != removing; then
      echo "$0: undocumented call to \`prerm $*'" 1>&2
      exit 0
    fi
    # Package $6 (version $7) which we depend on is being removed due
    # to a conflict with package $3 (version $4), and this package is
    # being deconfigured until $6 can be reinstalled.
    :

    ;;
  upgrade)
    # Prepare to upgrade FROM THIS VERSION of this package to version $2.
    :

    ;;
  failed-upgrade)
    # Prepare to upgrade from version $2 of this package TO THIS VERSION.
    # This is only used if the old version's prerm couldn't handle it,
    # and returned non-zero.  (Fix old prerm bugs here.)
    :

    ;;
  *) echo "$0: didn't understand being called with \`$1'" 1>&2
     exit 0;;
esac

exit 0
----------------------------------------------------------------------
#! /bin/sh
# postrm.skeleton
# Skeleton maintainer script showing all the possible cases.
# Written by Charles Briscoe-Smith, March-June 1998.  Public Domain.

# Abort if any command returns an error value
set -e

# This script is called twice during the removal of the package; once
# after the removal of the package's files from the system, and as
# the final step in the removal of this package, after the package's
# conffiles have been removed.

# Ensure the menu system is updated
: [ ! -x /usr/bin/update-menus ] || /usr/bin/update-menus

case "$1" in
  remove)
    # This package is being removed, but its configuration has not yet
    # been purged.
    :

    # Remove diversion
    : dpkg-divert --package foo --remove --rename \
    :             --divert /usr/bin/other.real /usr/bin/other

    # ldconfig is NOT needed during removal of a library, only during
    # installation

    ;;
  purge)
    # This package has previously been removed and is now having
    # its configuration purged from the system.
    :

    # Remove symlinks from /etc/rc?.d
    : update-rc.d foo remove >/dev/null

    ;;
  disappear)
    if test "$2" != overwriter; then
      echo "$0: undocumented call to \`postrm $*'" 1>&2
      exit 0
    fi
    # This package has been completely overwritten by package $3
    # (version $4).  All our files are already gone from the system.
    # This is a special case: neither "prerm remove" nor "postrm remove"
    # have been called, because dpkg didn't know that this package would
    # disappear until this stage.
    :

    ;;
  upgrade)
    # About to upgrade FROM THIS VERSION to version $2 of this package.
    # "prerm upgrade" has been called for this version, and "preinst
    # upgrade" has been called for the new version.  Last chance to
    # clean up.
    :

    ;;
  failed-upgrade)
    # About to upgrade from version $2 of this package TO THIS VERSION.
    # "prerm upgrade" has been called for the old version, and "preinst
    # upgrade" has been called for this version.  This is only used if
    # the previous version's "postrm upgrade" couldn't handle it and
    # returned non-zero. (Fix old postrm bugs here.)
    :

    ;;
  abort-install)
    # Back out of an attempt to install this package.  Undo the effects of
    # "preinst install...".  There are two sub-cases.
    :

    if test "${2+set}" = set; then
      # When the install was attempted, version $2's configuration
      # files were still on the system.  Undo the effects of "preinst
      # install $2".
      :

    else
      # We were being installed from scratch.  Undo the effects of
      # "preinst install".
      :

    fi ;;
  abort-upgrade)
    # Back out of an attempt to upgrade this package from version $2
    # TO THIS VERSION.  Undo the effects of "preinst upgrade $2".
    :

    ;;
  *) echo "$0: didn't understand being called with \`$1'" 1>&2
     exit 0;;
esac

exit 0
----------------------------------------------------------------------

-- 
Charles Briscoe-Smith
White pages entry, with PGP key: <URL:http://alethea.ukc.ac.uk/wp?95cpb4>
PGP public keyprint: 74 68 AB 2E 1C 60 22 94  B8 21 2D 01 DE 66 13 E2


--
To UNSUBSCRIBE, email to debian-devel-request@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org


Reply to: