Linux systemd-run 封装资源使用
序
之前我们讲了关于 systemctl
对各种服务或者说是 unit
进行了讲解,也讲了怎么创建一个 unit
,进行相关配置或者依赖设置等等。在使用 systemctl status xxx
时,我们可以发现对应的资源使用情况,如:
systemctl status chronyd
但如果创建一个 unit
每次都要通过配置文件,然后巴拉巴拉,其实还是很麻烦的,我们只需要使用 systemd-run
就可以轻而易举的创建一个 CGroup
,封装资源,运行命令,包装成一个 unit
。
systemd-run
快速认识
systemd-run
可以创建临时命令封装到 CGroup
中。CGroup
可以封装资源,运行任务。这样一个任务会变成我们熟悉的 unit
进行运行,然后可以通过 systemctl
进行管理。如:
# 后面会有完整实例
systemd-run -p MemoryLimit=5M -p CPUShares=100 --unit=mysleep --slice=test sleep 60
systemctl status mysleep
可以看到,我们直接创建了一个 service
,运行在 CGroup
中,并设置了一些资源限制。甚至我们可以查看下她的 service
配置文件:
systemctl cat mysleep
# 自动构建在了 /run/systemd/system/mysleep.service 中
格式与我们之前创建配置一致,所以可以认为 systemd-run
创建了一次性的 unit
运行。
如果在该任务运行完毕后,再次使用 systemctl
去查看:
systemctl status mysleep
systemctl cat mysleep
会发现该任务已经运行完毕,查看不到了。
描述
systemd-run
可以创建一个临时的 service
或者 scope
的 unit
,然后在里面运行简单的 COMMAND
命令。会创建对应的 service
文件,关联 path
、socket
、timer
等等,帮助在特定条件下启动临时的 service
。
通过 systemd-run
运行的命令,会在干净、独立的 CGroup
中;和其他的 unit
一样,可以使用 systemctl list-units
进行筛选查看;运行时,会使用 systemd
进程为父进程,以异步的方式在后台创建临时 service
运行,并且在命令执行之后返回结果(除明确 前台
执行外)。
使用
systemd-run
可以直接跟 bash
命令,全局默认运行程序:
systemd-run sleep 100
systemctl status run-5561
当然可以选择部分参数设置:
全量请参考,这里仅仅举例重要部分 https://www.linux.org/docs/man1/systemd-run.html
或
man systemd-run
–no-ask-password
需要切换用户执行时,不要进行密码验证
–scope
指定一个 unit
类型来创建任务,默认是 service
。
–unit=[name]
给 unit
指定名字,如果不指定,默认为 run-ID.service
格式。
–property / -p
给 unit
设置一个属性,这个属性列表是用空格分割的属性与值的键值对,比如:
systemd-run -p MemoryLimit=5M -p CPUShares=100 sleep 100
这里面大多数都是属性控制,需要参照的是 systemd.resource-control
,主要包含 CPU、Memory、IO 相关属性配置。
以下列举了常用的配置,大全请读者自行百度:https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html
或者参考该链接
选项 | 取值 | 含义 |
---|---|---|
CPUAccounting | yes/no | 如果为 yes,会开启CPU占用统计。 |
CPUWeight | 1-10000 | 默认100;CPU分配权重,控制Cgroup的 cpu.weight 属性,是系统正常运行时占比 |
StartupCPUWeight | 1-10000 | 默认100;CPU分配权重,控制Cgroup的 cpu.weight 属性,是系统启动过程时占比 |
CPUQuota | N% | 设置CPU时间上限,是一个百分数,占用单颗CPU的总时间多少 |
MemoryAccounting | yes/no | 如果为 yes,会开启MEM占用统计。 |
MemoryMin | N[KMGT] or N% | 进程保留的最低内存用量,可以使用512K进行表示,或者 10%相对系统的总物理内存;对应CGroup的memory.min |
MemoryLow | N[KMGT] or N% | 进程保障内存用量(除非其他的最低用量不够,才会少于这部分用量),可以使用512K进行表示,或者 10%相对系统的总物理内存;对应CGroup的memory.low |
MemoryHigh | N[KMGT] or N% | 进程柔性内存用量限制(如果超过会降低权重,并且尽量回收内存),可以使用512K进行表示,或者 10%相对系统的总物理内存;对应CGroup的memory.high |
MemoryMax | N[KMGT] or N% | 进程刚性内存用量限制(如果超过会被强制杀死),可以使用512K进行表示,或者 10%相对系统的总物理内存;对应CGroup的memory.max |
MemorySwapMax | N[KMGT] or N% | 进程刚性交换空间用量限制(如果超过会被强制杀死),可以使用512K进行表示,或者 infinity 不做限制;对应CGroup的memory.swap.max |
TasksAccounting | yes/no | 如果为yes,会进行任务数量统计 |
TasksMax | N or N% | 总任务数量的限制配置,可以为整数或者最大任务数量的百分比,或者 infinity 不做限制;对应CGroup的pids.max |
IOAccounting | yes/no | 如果为yes,会进行块设备IO统计 |
IOWeight | 1-10000 | 默认100;IO分配权重,控制Cgroup的 cpu.weight 属性,是系统正常运行时占比 |
StartupIOWeight | 1-10000 | 默认100;IO分配权重,控制Cgroup的 cpu.weight 属性,是系统启动过程时占比 |
Slice | string | 将unit放入那个slice中,主要是可以做层次、分组的资源分配或者依赖管理等。 |
–description=[string]
可以直接给 unit
添加一个描述性的字符串,如果不存在则是 COMMAND
本身。
–slice=[sliceName]
将该 unit
放入对应的 slice
中,默认为 system.slice
。与上面表格的 Slice
相同。
–remain-after-exit / -r
在 unit
执行完毕后,是否继续保持服务的存在,直到 stop
为止。如果不设置,在执行完 unit
后,该 unit
的信息会被全部删除。
–uid=[N]
以指定的 UID 身份进行 unit
的执行。
–gid=[N]
以指定的 GID 身份进行 unit
的执行。
–nice=[N]
执行 nice
谦让优先级。
–working-directory=[path]
指定工作目录进行 unit
运行。
–setenv=“[K=V]”
给 unit
传递一个环境变量,是一个列表使用空格隔开,内容为 KV 键值对,如:
systemd-run -r --setenv="name=huangyichun age=26" env
–cocllect / -G
当 unit
执行失败的时候,不会从内存中卸载,会一直保留在内存中,直到用户明确使用其他命令重启、或关闭。如果开启,资源回收会更加激进,在任务执行后被卸载,无论成功与否。
–on-active=[time]
在特定时间进行 unit
的运行,如:
systemd-run -r --on-active=60 env # 60秒后运行
systemctl status run-11249.service
systemctl status run-11249.service
systemctl status run-11249.service
返回值
0 为提交成功,1 为提交失败。
哪些地方可以使用
可以看到 systemd-run
可以封装一个小型的 shell
资源,并且可以指定到不同的用户运行,所以一般可以作为调度平台的使用。
shell
在调度中,会涉及大量 shell 脚本的使用,但是 shell 脚本的返回结果,资源封装等等做的并不够好,此时我们完全可以通过 unit
进行 shell 任务的调度。
spark-sql
举例一个大数据环境中,需要提交一个 spark-sql
任务,其实用 shell 也可以,但是如果我们还想保留完整的提交日志,尽量少的资源占用等等,都可以使用 systemd-run
来实现。