LINUX.ORG.RU

Не вкурю Systemd

 , ,


1

2

Добрый день, комрады!
Есть несколько проблем с systemd, которым не могу найти решения. помогите советом, - может кто сталкивался или просто умеет в systemd.
Есть сервер , на котором выполянется куча монотонных таймеров. Раз в 3 сек и таких таймеров больше сотни.
В консоль сыпет сообщения о их запуске и успешности\неуспешности оных.
https://ibb.co/5vQcyQp
Подобную бороду сыпет в syslog. Можно как-то отключить этот вывод в консоль , а еще лучше и в консоль, и в лог.

.timer:

[Unit]
Description=Collection screenshots for camera number 235 (qweqwe)
After=mariadb.service mnt-screenshots.mount
Requires=mariadb.service mnt-screenshots.mount
[Timer]
AccuracySec=1us
OnUnitActiveSec=3
OnBootSec=1
OnStartupSec=1
[Install]
WantedBy=timers.target

.service:

[Unit]
Description=Collection screenshots for camera number 235 (qweqwe)
After=mariadb.service mnt-screenshots.mount
Requires=mariadb.service mnt-screenshots.mount
[Service]
User=qweqwe
Type=forking
StartLimitInterval=0
StartLimitBurst=0
StandardOutput=null
StandardError=null
ExecStart=-/opt/scripts/get_screen.sh 235 > /dev/null 2>&1 &
Так же сам процесс systemd (pid 1) судя по всему упирается в процессор. Юзает одно ядро? Можно его «научить» использовать больше мощностей? Пруф: https://ibb.co/BtRhNWz

В консоль сыпет сообщения о их запуске и успешности\неуспешности оных.

Подобную бороду сыпет в syslog. Можно как-то отключить этот вывод в консоль , а еще лучше и в консоль, и в лог.

Смотри /etc/systemd/system.conf на предмет LogTarget= (должно быть journal-or-kmsg) и /etc/systemd/journald.conf на предмет ForwardTo{Syslog,Console}= и MaxLevel{Syslog,Console}= (выставь по вкусу, но точно не yes/info).

Так же сам процесс systemd (pid 1) судя по всему упирается в процессор

Ну вообще это не очень хорошо само по себе. У тебя там что, овер9000 этих юнитов? И насколько новый сам systemd — у него раньше было плохо с этим, потом оптимизировали.

intelfx ★★★★★ ()
Ответ на: комментарий от intelfx

Так это же глобальные параметры. Т.е. если я отключу тут лог, то он перестент отображать и логировать запуск прочих служб в том числе и системных. Я верно понимаю?
А по нагрузке - юнитов всего полторы сотни.

lasthappy ()
Ответ на: комментарий от lasthappy

Так это же глобальные параметры. Т.е. если я отключу тут лог, то он перестент отображать и логировать запуск прочих служб в том числе и системных. Я верно понимаю?

Да, верно. Возможности отключить вывод каких-то отдельных сообщений в systemd нет.

А по нагрузке - юнитов всего полторы сотни.

Тогда такого быть не должно. Что-то ещё не так. В любом случае, PID 1 systemd не многопоточный, потому что он в норме вообще не должен быть нагружен.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 2)
Ответ на: комментарий от intelfx

После перезагрузки проблема с повышенным потреблением CPU ушла совсем. Но если я массово изменю все эти полторы сотни таймеров и применю изменения (рестартану их), то нагрузка опять вернется...

lasthappy ()
Ответ на: комментарий от lasthappy

нагрузка опять вернется

На какое время? Это временный всплеск нагрузки или как только ты сделаешь эти действия, PID 1 начнёт жрать проц без остановки, пока не перезагрузишься?

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

Даже так скажу, если я выполню systemctl daemon-reload посе изменения 1 юнита. То нагрузка вырастет и очень надолго, хотя конца я не дожидался пока, ребутал - сервер не в продакшене.

lasthappy ()
Ответ на: комментарий от intelfx

Ну то есть у меня нет какого-либо простого решения, которое можно было бы сделать и всё будет зашибись. Либо у тебя в сетапе что-то, о чём ты не говоришь, либо это баг.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от intelfx

#cat /etc/systemd/system.conf | grep -v «#»

[Manager]
LogTarget=journal-or-kmsg
DefaultLimitNOFILE=500000

# cat /etc/systemd/journald.conf | grep -v «#»

[Journal]
ForwardToConsole=no
MaxLevelConsole=warning

Кстати по консольному выводу. Вот параметры выше. Если я сервер перезапущу. Один раз увижу как эти юниты запустились в консоли. Если же я изменю настройки и сделаю daemon-reexec, начинает сыпать.

lasthappy ()
.service:
[Unit]
Description=Collection screenshots for camera number *235* 
ExecStart=-/opt/scripts/get_screen.sh *235* > /dev/null 2>&1 &

почему не используются аргументы? проще же сделать по файлу темплейту на сервис и таймер, а номера камер через аргументы передавать, у меня примерно так для одного сервиса сделано, systemd жив при паре сотен оных.

тип мне кажется тоже должен быть one shot вместо forking. Точность прям 1us нужна? может 1s хватит?

ksim ()
Последнее исправление: ksim (всего исправлений: 2)
Ответ на: комментарий от ksim

Разброс в 1 секунду критичен. Если таймер на 3х секундный интервал рассчитан, то разброс, то получится, что будет интервал по факту варьироваться от 2-х до 4-х секунд...

lasthappy ()
Ответ на: комментарий от lasthappy

вот в скрипте и укажи нужные аргументы, так редактировать будешь не юнит а скрипт, разницы никакой, зато работать будет как тебе надо, а не как потный завещал.

deep-purple ★★★★★ ()
Ответ на: комментарий от deep-purple

На каждую камеру свой скрипт?)
Не логичнее ли будет один шаблонный скрипт, которому передается и соответствующего юнита идентификатор камеры. Да и юниты нужно редактировать все равно, т.к. интервал запуска скрипта может меняться.

lasthappy ()
Ответ на: комментарий от ksim

Как мне тогда оформить Unit, чтобы он запускал каждый раз скрипт ровно по расписанию, независимо от того когда был запущен и когда выполнился (или еще выполняется) предыдущий скрипт?
Короче, чтобы каждые 3 секунды он запускал еще одну копию скрипта

lasthappy ()
Ответ на: комментарий от lasthappy

Нет.

а) один юнит, дёргающий скрипт без опций и один этот скрипт и в нём конфигурация, функции и список вызовов для нужных камер.

б) сто юнитов дёргающих сто скриптов без опций и сто этих скриптов с конфигурациями под каждую камеру.

Хз что тебе ближе, проще и удобнее.

deep-purple ★★★★★ ()
Ответ на: комментарий от lasthappy

наверное что-то типа, сейчас времени проверить нет.

Type=oneshot
RemainAfterExit=true

camera@.timer

[Unit]
Description=Collection screenshots for camera number %i
After=mariadb.service mnt-screenshots.mount
Requires=mariadb.service mnt-screenshots.mount

[Timer]
AccuracySec=1us
OnUnitActiveSec=3
OnBootSec=1
OnStartupSec=1

[Install]
WantedBy=timers.target

camera@.service

[Unit]
Description=Collection screenshots for camera number %i
After=mariadb.service mnt-screenshots.mount
Requires=mariadb.service mnt-screenshots.mount

[Service]
User=qweqwe
Group=????
Type=oneshot
RemainAfterExit=true
StandardOutput=null # это зачем?
StandardError=null  # может стоить нормально с аутпутом обращаться?
ExecStart=-/opt/scripts/get_screen.sh %i

т.к. интервал запуска скрипта может меняться.

для тех где меняется можешь оверрайдить

ksim ()
Ответ на: комментарий от ksim

StandardOutput=null # это зачем?
StandardError=null # может стоить нормально с аутпутом обращаться?


Мне не нужно логировать события от ни никак. Чтобы не засирать лог, не тратитить дисковые операции и прочее.

lasthappy ()
Ответ на: комментарий от ksim

После добавления RemainAfterExit=true скрипт по таймеру разово только запускается и все. Судя по описанию так и должно быть. Исполняется он регулярно без этой опции, но время очередного запуска зависит от времени исполнения предыдущего скрипта.
Т.е. если скрипт выполняется 1 сек, то очередной запуск будет только через 3+1сек...

lasthappy ()
Ответ на: комментарий от lasthappy

Никто не знает?
Резюмирую. Скрипт не запускается в следующую итерацию таймера, если предыдущая итерация еще на завершилась. Как это обойти?
Нужно чтобы systemd запускал следующую итерацию ровно по таймеру вне зависимости от того, работает ли предыдущая. Пусть плодит их, как это делает, например, тот же крон

lasthappy ()
Ответ на: комментарий от lasthappy

можно запилить эти полторы сотни юнитов в отдельный контейнер nspawn, и уже в этом контейнере применить настройки, о которых писал intelfx. Тогда системные логи (надеюсь) останутся

anonymous ()
Ответ на: комментарий от lasthappy

Резюмирую. Скрипт не запускается в следующую итерацию таймера, если предыдущая итерация еще на завершилась. Как это обойти?

мне кажется никак, by design systemd не умеет один и тот же сервис запускать одновременно (что то и у других не припомню этого функционала, cron не в счёт, оно не init), ибо управление этим аттракционом будет кошмар, как например остановить 10тый запущенный процесс с помощью stop?

делай oneshot сервис, который запускает процесс твоего капчуринга и детачит его, таким образом сервис сразу завершится, а процесс продолжит засерать ваш сервер. пример который я дал у меня отработал на ура в таком случае.

ksim ()
Последнее исправление: ksim (всего исправлений: 1)
Ответ на: комментарий от lasthappy

мой минимальный рабочий пример такой: camera@.service:

[Unit]
Description=Collection screenshots for camera number %i

[Service]
Type=oneshot
KillMode=process
ExecStart=/opt/scripts/get_screen.sh %i

camera@.timer

[Unit]
Description=timer screenshots for camera number %i

[Timer]
AccuracySec=1us
OnCalendar=*:*:0/3

[Install]
WantedBy=timers.target

script

#!/bin/bash

/usr/bin/nohup /opt/scripts/get_screen_child.sh &>> /tmp/out.txt &

get_screen_child рандомно висящий до 10 секунд

ksim ()
Последнее исправление: ksim (всего исправлений: 1)
Ответ на: комментарий от ksim

nohup не нужен, достаточно & кмк, в остальном плюсую — ТС, вот твоё решение (ну как «решение», так себе костыль, но сойдёт) проблемы с запуском одного юнита несколько раз. Можно избавиться от промежуточного скрипта и запускать ExecStart=/bin/bash -c '/path/to/script &>>/path/to/log &'.

С логированием ничего сделать нельзя, разруливай на уровне syslog, если сильно нужно. Насчёт консоли — не понимаю, зачем тебе дублирование логов в консоль, причём обязательно на уровне info/notice.

intelfx ★★★★★ ()
Последнее исправление: intelfx (всего исправлений: 3)
Ответ на: комментарий от intelfx

С логами не критично, если нельзя, то нельзя. А вот про консоль - я в нее не дублирую. Он сам так по дефолту делал.
Явное указание параметра ForwardToConsole=no, решило проблему вроде.

lasthappy ()