如何在不启动相关服务的情况下安装软件包?

正如您可能已经知道的那样,默认情况下,当您在Debian或Ubuntu系统上安装软件包时,如果软件包包含服务,则通常在安装软件包时启用并自动启动该服务。

这对我来说是一个问题。

我发现自己需要pipe理构buildLXC容器的模板。 有几个容器,每个对应一个Debian或Ubuntu发行版。 (也有红帽的容器,但在这里没有关系。)

/var/lib/libvirt/filesystems/debian6_template /var/lib/libvirt/filesystems/debian7_template /var/lib/libvirt/filesystems/ubuntu1004_template /var/lib/libvirt/filesystems/ubuntu1204_template 

偶尔我会发现模板有一个丢失的包或需要一些其他的改变,所以我会chroot到他们来安装包。 不幸的是,当我这样做的时候,我发现了几个包的服务正在运行!

举个例子,我发现模板没有syslog守护进程,所以我安装了一个:

 for template in /var/lib/libvirt/filesystems/{debian,ubuntu}*_template; do chroot $template apt-get install rsyslog done 

并迅速结束了rsyslog运行的四个副本。 更不用说exim4的两个副本了。 哎呀!


我读过某处(虽然现在再也找不到了),但是在chroot中运行时不应该启动服务,但是这显然没有发生。

一个潜在可行的讨厌的黑客要求临时replace实际启动服务的各种命令,比如start-stop-daemoninitctl ,虽然这比我真正想做的工作要多得多。 如果我没有别的select,虽然…

这里的理想解决scheme是基于Debian的系统停止做这个废话,但是如果没有这个,可能是apt-get一个模糊或者没有logging的命令行选项?

如果不清楚的话,如果可能的话,我真的想保留任何与pipe理模板之外的模板相关的东西。

对于debian,你可以用policy-rc.d来做到这一点。 这里有一个解释 :

一个包的维护者脚本应该只通过invoke-rc.d,update-rc.d和LSB初始化脚本头文件与init系统进行交互…在执行动作之前,invoke-rc.d将会检查是否/usr/sbin/policy-rc.d是可执行文件,将在其命令行中使用相应的服务名称和当前运行级别号码进行调用,并根据其退出代码进行操作。 例如,返回值101将阻止计划的操作被采用。 这包括在软件包安装时自动启动服务以及停止在软件包移除服务,并减less软件包升级过程中的停止升级 – 重新启动仪式,只执行升级,可能会使旧版本的服务运行

由于您不希望任何服务启动,您的policy-rc.d脚本可以很简单

 #!/bin/sh exit 101 

这是pbuilder和Docker的mkimage-debootstrap等工具所使用的技术。

不幸的是,这种技术不适用于Ubuntu chroot。 与upstart init系统集成的软件包在安装过程中会调用/ usr / sbin / initctl而不是invoke-rc.d,initctl不会参考policy-rc.d。 根据upstart的作者 ,解决方法是用/ bin / truereplace/ sbin / initctl到符号链接。 你可以在mkimage-debootstrap中看到这个,他们可以

 dpkg-divert --local --rename --add /sbin/initctl ln -sf /bin/true sbin/initctl 

你可以做:

 export RUNLEVEL=1 for template in /var/lib/libvirt/filesystems/{debian,ubuntu}*_template; do chroot $template apt-get install rsyslog done exit 

我没有用chroottesting它,但它应该工作。 起初它设置了RUNLEVEL环境variables,所以apt-get启动的进程不会启动任何服务,因为他们会“认为”系统在单一模式下运行。 由于环境被修改的方式可能会影响将来的命令,因此在不再需要修改的环境时需要退出shell,这是通过退出命令来完成的。 可能有一些(罕见的)软件包不能在单一模式下正确安装(但在大多数情况下AFAIK应该不是问题)。