3

My goal is to prohibit installation/upgrade of a specific package if the system is not in a specific state (some pre-upgrade work needs to be done).

I attempted the DPkg::Pre-Invoke hook, but it does not receive any arguments:

DPkg::Pre-Invoke { "echo >&2 PREINVOKE [$@]"; };

just prints

PREINVOKE []

Is there a way to get the list of packages that are going to be touched from this hook? Or maybe a different hook will do it? The solution should better be system-wide, so solutions aliasing the apt-get command do not look feasible, unfortunately.

1 Answer 1

2

There is another hook that, when used carefully, helps get the job done. The hook name is DPkg::Pre-Install-Pkgs, and it is also an array just like Pre-Invoke. According to man apt.conf,

This is a list of shell commands to run before invoking dpkg(1). Like options this must be specified in list notation. The commands are invoked in order using /bin/sh; should any fail APT will abort. APT will pass the filenames of all .deb files it is going to install to the commands, one per line on the requested file descriptor, defaulting to standard input.

Specify a script in the hook like this

DPkg::Pre-Install-Pkgs { "/usr/local/libexec/somepackage-preinstall"; }

The script is invoked without arguments, and gets a list of .deb package filenames on its standard input. Now, it is important that the script is invoked not only for apt-get install, but also for apt-get remove (with empty input). So in the script you need to detect that the package that requires some pre-installation processing is actually among those passed to its standard input. This can be done like this

#!/bin/bash
grep -q '/somepackage_' || exit 0
... Do what you need here ...

grep attempts to match every filename on standard input against the pattern that should identify the package uniquely, and the script exits successfully if the apt-get install or apt-get upgrade was not invoked in a way to upgrade the package you are interested in. If you want also to get the name of the .deb file, you can use, for one, the following bashism

#!/bin/bash
read debfile < <(grep '/somepackage_') || exit 0

This usage guarantees that the $debfile variable will get exactly one package filename, to avoid surprises if more than one matches the input.

Remember that the file names are starting from the filesystem root, like /var/cache/apt/archives/acl_2.2.52-1_amd64.deb.

Since DPkg::Pre-Install-Pkgs is an array, all lines specifying it in multiple files in apt.conf.d are cumulative: each script will be invoked with the same input.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .