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.