Как прикрепить фоновый процесс к CGroup службы systemctl

Позвольте мне объяснить немного больше. У меня есть сервис на CentOS 7, который запускает скрипт sh. Затем сценарий разветвляется, скажем, на 4 других дочерних процесса. Если один из них умирает, я хочу запустить его из другого сервиса, но я хочу, чтобы он был присоединен к CGroups других трех процессов.

Таким образом, состояние systemctl myService показывает 4 процесса (после того, как основной скрипт завершает разветвление на 4 дочерних элемента). Затем, если один дочерний процесс будет убит, состояние systemctl myService покажет только 3 процесса в CGroup. Итак, как можно запустить отсутствующий и подключить его к CGroup других 3-х, чтобы в состоянии systemctl myService снова отображалось 4 дочерних элемента?

Пример:

Active: active (running) CGroup: /system.slice/myService.service - 1234 process1 - 1235 process2 - 1237 process4

Active: active (running) CGroup: /system.slice/myService.service - 1234 process1 - 1235 process2 - 1236 process3 - 1237 process4 Спасибо!

0 ответов

Если ты cat "/proc/$pid/cgroup" где $pid обозначает PID процесса, который принадлежит myService.service, вы увидите что-то вроде:

10:memory:/
9:blkio:/
8:pids:/system.slice/myService.service
7:perf_event:/
6:net_cls,net_prio:/
5:freezer:/
4:devices:/system.slice/myService.service
3:cpuset:/
2:cpu,cpuacct:/
1:name=systemd:/system.slice/myService.service

Вход name=systemd:/system.slice/myService.service имеет решающее значение. Делать systemd "ассимилировать" еще один процесс в сервисе, нужно повторить эту запись.

Обычно можно использовать cgclassify или же cgexec, Например, они работают нормально:

cgexec -g memory:/ -g pids:/system.slice/myService.service sleep 60 &
cgclassify -g cpuset:/ "$pid"

Но я не нашел способа заставить его работать с name=systemd:, Следующие команды не работают в моем Debian 9:

cgexec -g  name=systemd:/system.slice/myService.service sleep 60
cgexec -g  systemd:/system.slice/myService.service      sleep 60
cgexec -g '*systemd:/system.slice/myService.service'    sleep 60
cgexec -g '*:/system.slice/myService.service'           sleep 60

Подобные попытки с cgclassify (для уже запущенного процесса) и сбой. Однако вместо cgclassify ты можешь сделать это:

echo "$ pid"> /sys/fs/cgroup/systemd/system.slice/myService.service/tasks

Или если вам нужно sudo:

echo "$pid" | sudo tee /sys/fs/cgroup/systemd/system.slice/myService.service/tasks

После этого $pid появится в выводе systemctl status myService.service а также systemd будет считать процесс частью службы (например, он убьет его, если вы вызовете systemctl stop myService.service).

Чтобы имитировать исходный процесс, вам может потребоваться повторить другие записи. Например, для pids:/system.slice/myService.service любая из этих двух команд должна работать:

cgclassify -g pids:/system.slice/myService.service "$pid"
# or
echo "$pid" > /sys/fs/cgroup/pids/system.slice/myService.service/tasks

Иногда порождение процесса и изменение его группы (групп) позже может быть неоптимальным. Вы можете хотеть, чтобы процесс начался в надлежащих cgroups. Обычно вы делаете это с cgexec но (как указано выше) это, похоже, не работает с name=systemd:, Возможный подход:

sh -c '
  echo "$$" > /sys/fs/cgroup/systemd/system.slice/myService.service/tasks || exit 1
  cgclassify -g cpuset:/ -g devices:/system.slice/myService.service "$$" || exit 1
  # add more -g arguments if you need
  exec your_command with arguments
'

Хитрость в том, когда оболочка execс sleep это уже в правильных группах. Или даже:

sh -c '
  echo "$$" > /sys/fs/cgroup/systemd/system.slice/myService.service/tasks || exit 1
  exec cgexec -g cpuset:/ -g devices:/system.slice/myService.service your_command with arguments
  # add more -g arguments if you need
'

Из скрипта вы можете сделать это следующим образом:

nohup sh -c ' … ' &
Другие вопросы по тегам