让我再解释一下。我在 CentOS 7 上有一个服务,它启动了一个 sh 脚本。然后该脚本会分叉为其他 4 个子进程。如果一个进程挂了,我想从另一个服务启动它,但我希望它附加到其他 3 个进程的 CGroups。
因此,systemctl status myService 显示 4 个进程(在主脚本完成分叉为 4 个子进程之后)。然后,如果一个子进程被终止,systemctl status myService 只会显示 3 个进程进入 CGroup。那么,如何启动缺失的进程,然后将其附加到其他 3 个 CGroup,以便 systemctl status 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
谢谢!
答案1
如果您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
您可以这样做:
回显“$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
有时生成一个进程并稍后更改其 cgroup 可能不是最佳选择。您可能希望该进程开始在适当的 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
'
诀窍在于当 shellexec
连接到sleep
它时,它已经在正确的 cgroups 中。或者甚至:
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 ' … ' &