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