Как стать автором
Обновить

Комментарии 9

А у вас какой тип сервиса указан в unit-файле? Есть разные варианты поведения сервиса, но, да, systemd должен понимать, в какой момент сервис завершился, чтобы подчистить за ним оставшееся окружение.

Вот такой шаблон:

# systemctl cat user@1000.service
…
[Service]
User=%i
PAMName=systemd-user
Type=notify
ExecStart=/usr/lib/systemd/systemd --user
Slice=user-%i.slice
KillMode=mixed
Delegate=pids memory
TasksMax=infinity
TimeoutStopSec=120s
KeyringMode=inherit

Type=notify

Это для пользовальской сессии. А приложение-то как запускается?

"Ты хитрый."©
Чтобы более-менее внятно ответить на вопрос, надо размотать пол-системы.
Вот так "в лоб" мы ничего не видим:

# find / -type d -wholename '*/systemd/user/*'
/etc/systemd/user/graphical-session-pre.target.wants
/etc/systemd/user/sockets.target.wants
/etc/systemd/user/pipewire.service.wants
/etc/systemd/user/timers.target.wants
/etc/systemd/user/basic.target.wants

/usr/lib/systemd/user/sockets.target.wants
/usr/lib/systemd/user/vte-spawn-.scope.d

Но применив "магическое заклинание" "systemctl --user status" (из-под активного пользователя), видим куст поназапущенного.

В частности:

           │ ├─app-xswitcher@autostart.service
           │ │ └─ 2108 /usr/local/bin/xswitcher

Подробности:

# systemctl --user status app-xswitcher@autostart.service
● app-xswitcher@autostart.service - xswitcher
     Loaded: loaded (/home/xxx/.config/autostart/xswitcher.desktop; generated)
     Active: active (running) since Mon 2024-12-02 21:53:04 MSK; 14h ago
       Docs: man:systemd-xdg-autostart-generator(8)
   Main PID: 2108 (xswitcher)
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/app-xswitcher@autostart.service
             └─ 2108 /usr/local/bin/xswitcher

Видим, что некий "systemd-xdg-autostart-generator" взял шаблон из "autostart/xswitcher.desktop". И сгенерил по своему усмотрению вот такое:

cat /run/user/1000/systemd/generator.late/app-xswitcher@autostart.service
# Automatically generated by systemd-xdg-autostart-generator

[Unit]
Documentation=man:systemd-xdg-autostart-generator(8)
SourcePath=/home/xxx/.config/autostart/xswitcher.desktop
PartOf=graphical-session.target

Description=xswitcher
After=graphical-session.target

[Service]
Type=exec
ExecStart=:/usr/local/bin/xswitcher # (":" suppresses variable expansion)
Restart=no
TimeoutSec=5s
Slice=app.slice
WorkingDirectory=-/home/xxx

Исходный шаблон (с ним всё скучно):

[Desktop Entry]
Comment[ru_RU]=
Comment=
Exec=/usr/local/bin/xswitcher
GenericName[ru_RU]=
GenericName=
Icon=system-run
MimeType=
Name[ru_RU]=xswitcher
Name=xswitcher
Path=/home/xxx
StartupNotify=false
Terminal=false
TerminalOptions=\s
Type=Application
X-KDE-SubstituteUID=false
X-KDE-Username=

Таки да. Процесс (теперь) запускает именно systemd. Завернув в cgroup (подробности можно подглядеть в "/sys/fs/cgroup").

Просто по вашему исходному сообщению непонятно, вы сами написали unit-файл для вашего скрипта (я думал, что да, его и хотел увидеть) или же у вас какая-то автомагия конкретного дистрибутива Linux. Соответственно, чтобы понять, что и где не так, требовалось полное описание контекста.

Да, в systemd есть шаблоны сервисов (как в примере с пользовательской сессией), позволяющие инстанциировать сессию, подставив UID пользователя (например, 1000). А есть и генераторы, которые при запуске на основе найденных конфигов (например, тех же старых init-скриптов) создают временные unit-файлы в /run.

Вам надо поменять поведение системы в целом или для одного конкретного приложения/сервиса? Если для одного конкретного, то можно просто написать нужный unit-файл безо всяких шаблонов. Или пооверрайдить сгенерированный unit-файл своими параметрами. Если же для всех, можно попробовать пооверрайдить шаблон. Но я не советую так делать, ибо может поломаться совсем всё.

В linux "fork()" обозвали "clone()", но суть от этого не изменилась.

Вы какие-то странные утверждения делаете. В Linux fork -- это fork, это системный вызов из тех времён, когда в ядре не было неймспейсов, он не принимает никаких параметров. clone -- это другой, хоть и похожий, но более новый системный вызов, с помощью которого можно поместить дочерний процесс в другой неймспейс.

Начинаю копать и выясняю, что этот самый "mail" (который пакуют во всякие "mailutils", "mailx" и т.п.) работает, оказывается, в асинхронном режиме!

Применительно к процессам "асинхронный режим" -- это, на мой взгляд, неправильная терминология. mail форкается и выходит, не дожидаясь завершения дочернего процесса.

но пока не знаю, как правильно её купировать.

Вызывать в вашем юните mail с параметром -S sendwait. В чём проблема с KDE я не понял.

Больше можно не думать обо всех этих "демонизациях", логировании и прочей IT-гигиене. "Сделай тяп-ляп, а systemd за тобой подотрёт". В любой момент может оказаться, что писатель очередного ПО всю зачистку переложил на systemd.

Так ведь в этом и смысл systemd. Ваш юнит просто пишет свой вывод в stdout/stderr, это всё логгируется с помощью journald. Можно настроить юнит так, чтобы юнит перезапускался, если процесс завершается с ненулевым статусом. И т.д. и т.п., у systemd масса всякого функционала.

systemd теперь является де-факто стандартом в большинстве линкус-дистрибутивов, разработчику больше не нужно самому имплементировать демонизацию, логгирование и т.д. На самом деле, вероятность того, что писатель очередного ПО как-то криво сделает зачистку гораздо выше, чем вероятность того, что её криво сделает systemd.

Если вы пишете софт под Devuan или под какие-то очень старые системы на SysVinit -- тогда да, надо самому имплементировать всё это добро.

Спасибо, поправил статью по первым двум пунктам (добавил цитаты).

Вызывать в вашем юните mail с параметром -S sendwait. В чём проблема с KDE я не понял.

Чтобы включить "sendwait", нужно осознавать в чём тут фокус. Надеюсь что моя заметка сократит кому-нибудь время на дебаг. Проблема у меня на локалхосте (KDE) просто имеет ту же самую причину.

Удержать в голове все "нюансы" systemd для меня, например, как для "ассоциатива" — нереально. Пролистываю мануалы по мере возникновения задач, пропуская мимо всё не связанное. Постепенно число связей растёт. Как-то так…
И вот тут — да, отношусь к systemd с некоторым скепсисом, как неплохо информированный оптимист. Кое-что — вот прямо очень удобно. К примеру, контрольные группы по CPU/blkio или навешивание приоритетов для OOM. С другой стороны, полностью динамический порядок запуска — полный кошмар при отладке. Или вот прохождение квеста "э, а где мой dmesg?". На стыке ядра (буфера 2к бывает маловато) и journald.
…Что касается "очень старых систем", то они никуда не девались. Просто в новом-модном это называется "initrd"/"initramfs" и туда мало кто лазает. Да, там теперь "из коробки" дирижирует systemd. Но (к счастью) оставлена возможность запуститься в шелл и провести необходимые (ремонтные) мероприятия. Вплоть до "восхода солнца вручную".

Я согласен с тем, что дебажить такого рода проблему как с форками mail в systemd совсем не тривиально. Я бы попробовал включить LogLevel=debug и посмотреть, есть ли какая-то информация о том, какие процессы systemd убивает при завершении юнита.

Давно не смотрел openSUSE. Поставил на виртуалку openSUSE Leap 15.6 с KDE Plasma(openSUSE-Leap-15.6-NET-x86_64-Media.iso)
Долго тупил как включить sudo юзверю(помимо группы wheel и правки sudoers)
Теперь надо ставить пакеты sudo-policy-wheel-auth-self system-group-wheel и возможно system-user-mail
Еще интересный пакет systemd-status-mail - Send a mail if a systemd.timer fails and/or succeeds
zypper se wheel mail
Рекомендую почитать(лучше на English)
https://wiki.archlinux.org/title/Systemd_(Русский)/Timers_(Русский)
https://wiki.archlinux.org/title/Systemd/Timers
https://wiki.archlinux.org/title/Systemd_(Русский)/User_(Русский)
https://wiki.archlinux.org/title/Systemd/User

openSUSE Leap 15.6 с KDE Plasma

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации