我的目标是,如果系统未处于特定状态(需要完成一些升级前工作),则禁止安装/升级特定包。
我尝试了DPkg::Pre-Invoke
钩子,但它没有收到任何参数:
DPkg::Pre-Invoke { "echo >&2 PREINVOKE [$@]"; };
只是打印
PREINVOKE []
有没有办法获取将要从此挂钩触及的包列表?或者也许一个不同的钩子可以做到这一点?该解决方案最好是在系统范围内的,因此apt-get
不幸的是,使用别名命令的解决方案看起来不可行。
答案1
还有另一个钩子,如果小心使用,可以帮助完成工作。钩子名称是DPkg::Pre-Install-Pkgs
,它也是一个数组,就像Pre-Invoke
.根据man apt.conf
,
这是调用 dpkg(1) 之前要运行的 shell 命令列表。与选项一样,这必须以列表表示法指定。使用 /bin/sh 按顺序调用命令;如果任何失败 APT 将中止。 APT 会将要安装的所有 .deb 文件的文件名传递给命令,请求的文件描述符上每行一个,默认为标准输入。
在钩子中指定一个脚本,如下所示
DPkg::Pre-Install-Pkgs { "/usr/local/libexec/somepackage-preinstall"; }
该脚本在不带参数的情况下调用,并在其标准输入上获取 .deb 包文件名列表。现在,重要的是不仅要为 调用脚本apt-get install
,还要为apt-get remove
(使用空输入)调用脚本。因此,在脚本中,您需要检测需要进行一些预安装处理的包实际上是在传递给其标准输入的包中。这可以这样做
#!/bin/bash
grep -q '/somepackage_' || exit 0
... Do what you need here ...
grep 尝试将标准输入上的每个文件名与应唯一标识包的模式进行匹配,如果未以升级您感兴趣的包的方式调用apt-get install
或,则脚本将成功退出。如果您还想获取名称apt-get upgrade
对于 .deb 文件,您可以使用以下 bashism
#!/bin/bash
read debfile < <(grep '/somepackage_') || exit 0
这种用法保证$debfile
变量将准确获得一个包文件名,以避免多个包文件名与输入匹配时出现意外。
请记住,文件名是从文件系统根目录开始的,例如/var/cache/apt/archives/acl_2.2.52-1_amd64.deb
.
由于DPkg::Pre-Install-Pkgs
是一个数组,因此在多个文件中指定它的所有行apt.conf.d
都是累积的:每个脚本都将使用相同的输入调用。