Как я могу установить пакеты без запуска связанных служб?

13

Как вы, вероятно, знаете, по умолчанию при установке пакета в системе на основе 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

Иногда я обнаруживаю, что в шаблонах отсутствует пакет или требуется какое-то другое изменение, поэтому я добавлю в них хром для установки пакета. К сожалению, когда я это делаю, у меня запускается несколько копий службы пакета!

В качестве примера я обнаружил, что в шаблонах нет демона syslog, поэтому я установил его:

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

И быстро запустил четыре запущенных копии rsyslog. Не говоря уже о двух экземплярах exim4. К сожалению!


Я где-то читал (хотя я не могу найти это снова сейчас), что он не должен запускать службы при запуске в chroot, но это явно не происходит здесь.

Один потенциально жизнеспособный неприятный взлом требует временной замены различных команд, которые фактически запускают службы, таких как start-stop-daemonи initctl, хотя это намного больше работы, чем я действительно хотел сделать. Если у меня нет другого выбора, хотя ...

Идеальным решением здесь было бы для систем на основе Debian прекратить делать это дерьмо, но если это не удастся, возможно, для скрытой или недокументированной опции командной строки для apt-get?

На случай, если неясно, я действительно хочу оставить что-либо, связанное с управлением шаблонами, за пределами шаблонов, если это возможно.

Майкл Хэмптон
источник

Ответы:

23

Для Debian вы можете сделать это с помощью policy-rc.d . Вот одно из объяснений :

Предполагается, что сценарии сопровождающего пакета взаимодействуют только с системой init с помощью invoke-rc.d, update-rc.d и заголовков сценариев LSB init ... invoke-rc.d перед выполнением своего действия проверит, /usr/sbin/policy-rc.d является исполняемым, вызывает его с соответствующим именем службы и текущим номером уровня выполнения в командной строке и действует в соответствии с кодом выхода. Например, возвращаемое значение 101 предотвратит выполнение запланированного действия. Это включает в себя автоматический запуск службы после установки пакета, а также остановку службы при удалении пакета и уменьшает ритуал stop-upgrade-restart во время обновления пакета до простого выполнения обновления, которое может оставить старую версию службы запущенной.

Поскольку вы не хотите, чтобы какие-либо службы запускались, ваш сценарий policy-rc.d может быть простым

#!/bin/sh
exit 101

Это техника, используемая такими инструментами, как pbuilder и Docker mkimage-debootstrap .

К сожалению, этот метод не работает с chroot Ubuntu . Пакеты, которые интегрируются с системным вызовом upstart init / usr / sbin / initctl вместо invoke-rc.d во время установки, а initctl не обращается к policy-rc.d. Согласно автору выскочки, обходной путь должен заменить / sbin / initctl символической ссылкой на / bin / true в chroot. Вы можете увидеть это в mkimage-debootstrap, они делают

dpkg-divert --local --rename --add /sbin/initctl
ln -sf /bin/true sbin/initctl
Sciurus
источник
Это кажется довольно чистым, хотя его также нужно будет удалить перед созданием контейнера из шаблона.
Майкл Хэмптон
1
Спасибо за это. Я могу в конечном итоге просто сорвать скрипт Docker mkimage-debootstrap, так как они, похоже, в основном решили эту проблему.
Майкл Хэмптон
4

Ты можешь сделать:

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

Я не проверял это с chroot, но это должно работать. Сначала он устанавливает переменную среды RUNLEVEL, поэтому процессы, инициированные apt-get , не будут запускать какие-либо службы, потому что они будут «думать», что система работает в одиночном режиме. Поскольку среда модифицируется так, как это может повлиять на будущие команды, необходимо выйти из оболочки, когда модифицированная среда больше не нужна, это достигается с помощью команды выхода в конце. Там могут быть некоторые (редкие?) Пакеты , которые не будут установлены должным образом в одном режиме (но AFAIK это не должно быть проблемой в большинстве случаев).

DavisNT
источник
Является export RUNLEVEL=1важной частью здесь? Что именно это вызывает?
Майкл Хэмптон
@MichaelHampton Я считаю, что переменная среды RUNLEVEL обеспечит текущий уровень выполнения. В этом случае он просто перезаписывает его, поэтому любое приложение будет думать, что оно работает на 1. Это своего рода «клудж», но этого должно быть достаточно.
WinkyWolly
Добавлено пояснение к оригинальному ответу. В основном это то, что сказал @WinkyWolly.
DavisNT
К сожалению, rsyslogэто был один из «редких» пакетов, который полностью взорвался при попытке установить этот путь. Тем не менее, это может быть полезно, так что вы можете сохранить повышенный голос :)
Майкл Хэмптон