systemd 方式启动 agent 踩坑记录
systemd 机制统一了不同 Linux 发行版的服务管理方式, 不过也引入了一些不可预知的问题. 本文则记录以 systemd 方式启动 agent(daemon 进程, 可执行系统命令, 采集数据等
) 服务引入的一些问题.
重启 agent 服务时也重启服务的子进程
比如以下 systemd 服务:
[Unit]
Description=agent auto start
[Service]
Type=simple
RemainAfterExit=yes
ExecStart=/tmp/agent.sh
[Install]
WantedBy=multi-user.target
通过 agent 执行 nohup sleep xxx
命令, 其对应的父进程即为 systemd 1
号进程:
root 62003 1 0 14:07 ? 00:00:00 sleep 300
root 62004 1 0 14:07 ? 00:00:00 sleep 200
从 systemd 服务状态来看, sleep 等进程和 agent 会同属于一个 CGroup
控制组, 如下所示:
● testagent.service - agent auto start
Loaded: loaded (/usr/lib/systemd/system/testagent.service; disabled; vendor preset: disabled)
Active: active (exited) since Thu 2023-01-07 14:07:37 CST; 3s ago
Process: 62001 ExecStart=/tmp/agent.sh (code=exited, status=0/SUCCESS)
Main PID: 62001 (code=exited, status=0/SUCCESS)
Memory: 360.0K
CGroup: /system.slice/testagent.service
├─62003 sleep 300
└─62004 sleep 200
此时再重启 testagent 服务, 则同控制组下的所有进程都会重启(即便以 nohup 启动). 如果想避免此类问题, 可以修改 systemd 服务的 KillMode
模式, 如下所以重启 agent 服务的时候不会充底下的子进程. 如下所示:
[Unit]
Description=agent auto start
[Service]
Type=simple
KillMode=process # 调整 KillMode 模式
RemainAfterExit=yes
ExecStart=/tmp/agent.sh
[Install]
WantedBy=multi-user.target
KillMode 模式说明见 systemd-killmode
重启 agent 服务时, 如何实现让有些进程重启, 有些不重启?
如上所示, KillMode
模式仅 kill 了父进程, 子进程会全部忽略, 但如果想让 agent 下运行的一些进程不退出(比如正在运行的重要进程), 一些进程退出(一些进程可能依赖 agent 服务功能) 就需要考虑实现以下几点:
1. 不退出的进程不属于 agent 服务的控制组;
2. 需要退出的进程属于 agent 服务的控制组;
这种情况下就不能使用 KillMode
模式, 需要依旧使用默认的 control-group
模式. 同样的 nohup ...
方式也不能使用. 要实现这种需求, 可以考虑以下两种方式实现目标 1, 更多见: lauch-process-outside-systemd-Cgroup.
方式一
通过 agent 执行 nohup ...
命令的时候以下面方式执行, 将新起的进程 pid 放到 cgroup 顶层, 脱离 agent 服务的控制组:
# centos 示例
nohup cmd &
echo $! >/sys/fs/cgroup/systemd/tasks
ubuntu 18 等需要将 pid 同时写到以下文件:
/sys/fs/cgroup/systemd/cgroup.procs /sys/fs/cgroup/unified/cgroup.procs
方式二
通过 agent 来以临时的 systemd 服务执行命令, 脱离 agent 服务的控制组, 如下所示:
systemd-run --unit sleep_test_50 --scope --slice=sleep_test nohup sleep 300 & >/tmp/some.log &
更多说明见: systemd-run.
其它问题
systemd 资源限制(man systemd.resource-control
)目前(Centos 7 中)不支持 net 限速, 只能通过 CPU, MEM, IO
进行限制. 大多数情况下限制 CPU 也能等同打到限速 net 的目录(比如 cpulimit 工具). systemd 限制资源示例见: 使用 systemd 限制系统资源.