
Я создаю машину Debian Bookworm, которая будет служить менеджером контейнеров LXC. Я использую непривилегированные контейнеры LXC, запущенные с помощью команды lxc-unpriv-start, которая создает область действия пользователя systemd. Я создаю службу, которая запускает мои контейнеры при запуске сервера и запускает чистое завершение работы при остановке службы. Для завершения работы каждого контейнера может потребоваться 2 или 3 минуты. Если я вручную останавливаю основную службу, все работает хорошо. Проблема возникает, когда я завершаю работу сервера, потому что моя служба правильно ждет завершения работы контейнеров, но в то же время systemd-logind убивает все пользовательские сеансы, жестоко убивая и мой контейнер.
Я моделирую ситуацию, создавая оболочку только для сна, и запускаю ее с помощью
/usr/bin/systemd-run --user --scope -p "Delegate=yes" wait.sh &
и он убивается при выключении. Как мне избежать этого убийства?
решение1
Linger должен решить эту проблему.
Отhttps://www.freedesktop.org/software/systemd/man/loginctl.html
Включить/отключить задержку пользователя для одного или нескольких пользователей. Если включено для определенного пользователя, менеджер пользователей создается для пользователя при загрузке и сохраняется после выхода из системы. Это позволяет пользователям, не вошедшим в систему, запускать долго работающие службы. Принимает одно или несколько имен пользователей или числовых UID в качестве аргумента. Если аргумент не указан, включает/отключает задержку для пользователя сеанса вызывающего.
loginctl enable-linger <username>
Включение задержки для сеанса пользователя позволит вашим контейнерам продолжать работу даже после выхода из системы или во время выключения системы. Это должно помешать systemd-logind принудительно завершить сеанс пользователя и связанные с ним контейнеры, предоставив им возможность завершить работу корректно.
решение2
Предполагая, что команда остановки контейнера "блокируется" (т. е. завершается после остановки контейнера), вы, вероятно, можете запустить команду запуска контейнера с помощью пользовательской службы systemd, а не напрямую из оболочки. Предположим, вам нужно запустить несколько контейнеров, вы можете написать шаблон службы в $HOME/.config/systemd/user/
. Имя файла шаблона службы должно иметь @
перед .service
(например [email protected]
, ).
Вот вам пример:
[Unit]
PartOf=%i.scope
After=%i.scope
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/systemd-run --user --scope -u %i sh -c 'sleep 1d &'
ExecStop=/usr/bin/sleep 1m
Как видите, имя области действия должно быть «известным», а не сгенерированным.
С помощью шаблона вы теперь можете запустить контейнер, например, с помощью systemctl --user start test@container-a
. Теперь вы должны увидеть, что соответствующая область действия сохраняется до тех пор, пока не остановится ее служба «агента» (т. е. команда ExecStop=
не завершится).
Вам может потребоваться выполнить этот запуск systemctl --user daemon-reload
каждый раз, когда вы вносите изменения в файл(ы) службы (шаблона).
P.S. Очевидно, что если вам необходимо передать дополнительные аргументы, специфичные для контейнера (которые не являются той же строкой, что и имя области действия) в команду запуска/остановки контейнера, вам, вероятно, придется написать несколько служебных файлов вместо использования шаблона.