Как прикрепить фоновый процесс к 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 ' … ' &