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

Mic*_*ton 16 package-management ubuntu debian

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

这对我来说是个问题。

我发现自己需要管理用于构建 LXC 容器的模板。有几个容器,每个容器对应一个 Debian 或 Ubuntu 版本。(也有基于 Red Hat 的容器,但它们在这里不相关。)

/var/lib/libvirt/filesystems/debian6_template
/var/lib/libvirt/filesystems/debian7_template
/var/lib/libvirt/filesystems/ubuntu1004_template
/var/lib/libvirt/filesystems/ubuntu1204_template
Run Code Online (Sandbox Code Playgroud)

偶尔我会发现模板缺少包或需要一些其他更改,因此我将 chroot 到它们以安装包。不幸的是,当我这样做时,我最终会运行该软件包的服务的多个副本!

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

for template in /var/lib/libvirt/filesystems/{debian,ubuntu}*_template; do
    chroot $template apt-get install rsyslog
done
Run Code Online (Sandbox Code Playgroud)

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


我在某处读到(虽然我现在找不到了)它不应该在 chroot 中运行时启动服务,但这显然不会在这里发生。

一个潜在可行的讨厌的 hack要求临时替换实际启动服务的各种命令,例如start-stop-daemoninitctl,尽管这比我真正想做的工作要多得多。如果我别无选择,虽然...

这里的理想解决方案是让基于 Debian 的系统停止做这种废话,但如果失败,可能是apt-get?

如果不清楚,如果可能的话,我真的希望在模板之外保留与管理模板相关的任何内容。

sci*_*rus 25

对于 debian,您可以使用policy-rc.d执行此操作。这是一种解释

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

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

#!/bin/sh
exit 101
Run Code Online (Sandbox Code Playgroud)

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

不幸的是,这种技术不适用于 Ubuntu chroots。与 upstart init 系统集成的软件包在安装期间调用 /usr/sbin/initctl 而不是 invoke-rc.d,并且 initctl 不咨询 policy-rc.d。根据 upstart 的作者,解决方法是在 chroot 中将 /sbin/initctl 替换为指向 /bin/true 的符号链接。您也可以在 mkimage-debootstrap 中看到这一点,它们确实如此

dpkg-divert --local --rename --add /sbin/initctl
ln -sf /bin/true sbin/initctl
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你。我可能最终不得不撕掉 Docker 的 mkimage-debootstrap 脚本,因为他们似乎已经基本上解决了这个问题。 (2认同)

Dav*_*sNT 5

你可以做:

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

我还没有用 chroot 测试过它,但它应该可以工作。首先它设置了 RUNLEVEL 环境变量,所以由 apt-get 启动的进程不会启动任何服务,因为它们会“认为”系统在单模式下运行。由于环境的修改可能会影响未来的命令,因此当不再需要修改的环境时,需要退出 shell,这是通过最后的exit命令完成的。有可能不会以单一模式(但据我所知这在大多数情况下,应该不会有问题)正确安装一些(少见?)封装。