Про systemd и автозапуск десктопных приложений
После переезда на openSUSE 15.5 я столкнулся с некой странностью. Автозапускаемые после старта приложения стали падать при попытке перезапуска.
Тут надо сказать, что сама по себе идея само-перезапуска (по крайней мере, в мире POSIX) достаточно простая и примитивная. Стартуем новый процесс, копируя ему всё своё окружение (не забывая про открытые файлы) и завершаемся. PPid при этом сбрасывается в наш бывший родительский, и вот. Имеем новый процесс, выглядящий (за исключением pid, конечно) ровно так же как и предыдущий.
Подробнее в дебри я тут лезть не буду. Кому интересно глубже — гуглите реализацию «fork-exec». В linux «fork ()» обозвали «clone ()», но суть от этого не изменилась. Вот тут — побольше философии.
На этой технике («respawn») работает в т.ч. обновление всякого десктопного софта. (Если вы конечно ему доверите такое вытворять у себя в системе.) Тот же клиент telegram. Ну и в своём xswitcher я тоже вкрутил подобную возможность.
И вот она-то наглухо «отвяла» после обновления ОС. Везде где была. Попытки дебага показывали что процесс запускается, начинает работать и затем молча дохнет. (Получая то ли sigterm, то ли sigkill. Я поленился встроить в xswitcher обработчик, за что и поплатился непонятками.)
Можно было бы ещё долго удивляться новой странной «магии», если бы не помог случай. Выпуская один хитрый сценарий для контроля топологии сети, решил «быть модным» и вместо всяких cron
повесить его на systemd.timer
. (Штука там достаточно автономная, так что текущий дизайн не ломает.)
И вот, «на голубом глазу» пишу в юнит-файле:
ExecStart=/bin/bash -c 'ERR=`/usr/local/sbin/xxx-check-topology.sh 2>&1` || (echo "$ERR" | /usr/bin/mail -s "xxx topology error(s) found" root)'
Раскидываю по местам. …И удивляюсь, что почты как-то меньше ожидаемого.
Как так? «Руками» запускаю — вот она, ругань. В зачищенном окружении (обычная проблема для башатины) — тоже. Начинаю копать и выясняю, что этот самый »mail
» (который пакуют во всякие »mailutils
»,»mailx
» и т.п.) работает, оказывается, в асинхронном режиме! (И имеет спец. ключ »-Ssendwait
» на случай когда так не надо.)
Начинаю гуглить и вижу, что народ на это натыкается достаточно массово. По причине systemd.kill. Начиная с некоторой версии, systemd
(безопасно/отказоустойчиво/инклюзивно/wtfElse) расстреливает всё содержимое cgroup
при завершении запущенного им процесса. Однако, если процесс изначально стартовал как-то ещё и потом был «сброшен» на systemd-user
, этот фокус не работает.
Поправьте, если я ошибаюсь. На примере KDE.
Вариант »
systemd
». Запустившийся »systemd --user
» дёргает условный «kstart». «Вон по тому списку.» Тот, в свою очередь, форкает то что заказано. И самоустраняется. Запущенная софтина (kwin
и что там поназаказывали в автозапуск) в итоге «повисает на шее»systemd
, и тот регистрирует процесс у себя. А увидев, что упало — экологично киляет всех потомков.Вариант «запустил из KDE». Когда я командую «запусти мне
bash
», происходит примерно так. Некий условный »kded
» (не знаю, кто на самом деле в KDE запуском заведует) дёргает »kstart
». Запускается окошко »konsole
» (или ещё какой-нибудь терминал). Тот, в свою очередь, стартуетbash
. Из которого можно скомандовать запуск ещё чего-нибудь.В этом месте я продолжаю кое-что не понимать.
# grep PPid /proc/$$/status PPid: 15589 # grep PPid /proc/15589/status PPid: 2967
»bash
порождён konsole
, konsole
порождён systemd
(2967 — это он самый).»
В моей картине мира, родителем должен был бы быть заказчик всего этого банкета (какой-нибудь резидентный процесс KDE).
Но теперь можно респавниться как угодно. Systemd не обращает на шалости такого процесса никакого внимания.
…Вот такое сегодня получилось эссе. Проблему я подсветил, но пока не знаю, как правильно её купировать.
С одной стороны, можно просто «дать по рукам»
systemd
. Там есть (см. по ссылке выше) крутилка «не убивать». Но, глядя на перспективу, я так делать опасаюсь. Плод трудов известного сотрудника Micro$oft, конечно, не абсолютное зло. Но однозначно приучает к безалаберности. Больше можно не думать обо всех этих «демонизациях», логировании и прочей IT-гигиене. «Сделай тяп-ляп, аsystemd
за тобой подотрёт». В любой момент может оказаться, что писатель очередного ПО всю зачистку переложил наsystemd
.С другой стороны, можно попробовать как-то надурить «надзирателя». Написать некую копеечную резидентную прокладку, как вариант. Но такой способ мне видится некрасивым.
На хабре достаточно людей с глубоким пониманием «кухни» ОС. Жду соображений «как правильно» в комментариях.
Всем удачи!