Избежать уничтожения области действия пользователя systemd при завершении работы

Избежать уничтожения области действия пользователя systemd при завершении работы

Я создаю машину 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. Очевидно, что если вам необходимо передать дополнительные аргументы, специфичные для контейнера (которые не являются той же строкой, что и имя области действия) в команду запуска/остановки контейнера, вам, вероятно, придется написать несколько служебных файлов вместо использования шаблона.

Связанный контент