Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

As you're probably aware, by default when you install a package on a Debian or Ubuntu based system, if the package contains a service, that service will generally be enabled and started automatically when you install the package.

This is a problem for me.

I've found myself needing to manage templates for building LXC containers. There are several containers, each corresponding to a Debian or Ubuntu release. (There are also Red Hat-based containers, but they aren't relevant here.)

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

Occasionally I will find that the templates have a missing package or need some other change, so I will chroot into them to install the package. Unfortunately when I do that, I wind up with several copies of the package's service running!

By way of example, I found the templates didn't have a syslog daemon, so I installed one:

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

And promptly wound up with four copies of rsyslog running. Not to mention two copies of exim4. Oops!


I read somewhere (though I can't find it again now) that it's not supposed to start services when running in a chroot, but that clearly isn't happening here.

One potentially viable nasty hack calls for temporarily replacing the various commands which actually start services, such as start-stop-daemon and initctl, though this is a lot more work than I really wanted to do. If I have no other choice, though...

The ideal solution here would be for Debian-based systems to stop doing this crap, but failing that, perhaps an obscure or undocumented command line option for apt-get?

In case it wasn't clear, I really want to keep anything related to managing the templates outside the templates, if possible.

share|improve this question

2 Answers 2

up vote 10 down vote accepted
+250

For debian you can do this with policy-rc.d. Here's one explanation:

A package’s maintainer scripts are supposed to only interface with the init system by means of invoke-rc.d, update-rc.d and the LSB init script headers... invoke-rc.d will, before taking its action, check whether /usr/sbin/policy-rc.d is executable, will call it with the respective service name and the current runlevel number on its command line and act according to its exit code. For example, a return value of 101 will prevent the planned action from being taken. This includes the automated start of the service upon package installation as well as the stop of the service on package removal and reduces the stop-upgrade-restart ritual during package upgrades to just performing the upgrade which might leave the old version of the service running

Since you don't want any services to ever start, your policy-rc.d script can be simply

#!/bin/sh
exit 101

This is the technique used by tools like pbuilder and Docker's mkimage-debootstrap.

Unfortunately, this technique does not work with Ubuntu chroots. Packages that integrate with the upstart init system call /usr/sbin/initctl instead of invoke-rc.d during installation, and initctl doesn't consult policy-rc.d. According to upstart's author the workaround is to replace /sbin/initctl with a symlink to /bin/true in a chroot. You can see this in mkimage-debootstrap as well, they do

dpkg-divert --local --rename --add /sbin/initctl
ln -sf /bin/true sbin/initctl
share|improve this answer
    
This seems pretty clean, though it also will have to be removed before creating a container from the template. –  Michael Hampton Jan 15 at 17:14
    
Thanks for this. I may end up just having to rip off Docker's mkimage-debootstrap script, as they seem to have mostly solved this problem. –  Michael Hampton Feb 9 at 22:40

You can do:

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

I haven't tested it with chroot, but it should work. At first it sets RUNLEVEL environment variable, so processes initiated by apt-get will not start any services, because they will "think" system is running in single mode. As environment is modified the way it may affect future commands, it is required to exit shell when modified environment is no longer needed, this is accomplished by exit command at the end. There may be some (rare?) packages that won't install properly in single mode (but AFAIK this should not be problem in most cases).

share|improve this answer
    
Is export RUNLEVEL=1 the important part here? What exactly does it cause to happen? –  Michael Hampton Feb 6 at 17:01
    
@MichaelHampton I believe the RUNLEVEL environmental variable will provide the current run level. In this instance he's just overwriting it so any application will think it's running on 1. It's sort of "kludge" but should suffice. –  WinkyWolly Feb 6 at 23:29
    
Added explanation to original answer. Basically this is what @WinkyWolly said. –  DavisNT Feb 7 at 11:21
    
Unfortunately rsyslog happened to be one of the "rare" packages which blew up completely when trying to install this way. This may still be useful, though, so you can keep the upvote :) –  Michael Hampton Feb 9 at 22:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.