systemd-run
创建并启动一个临时的 .scope
、.service
、.path
、.socket
或 .timer
单元,并在其中运行 COMMAND 命令,可以结合 cgroup 限制资源的使用,并支持使用 systemd 管理该进程
介绍
- 帮助:
man systemd-run
.service
是一个或一组进程,由 systemd
依据单位配置文件启动,并可以作为一个整体被启动或终止
.scope
一组外部创建的进程,前台进程。由强制进程通过 fork()
函数启动和终止、之后被 systemd
在运行时注册的进程,scope
会将其封装。例如:用户会话、容器和虚拟机被认为是 scope
slice
一组按层级排列的单位
slice
并不包含进程,但会组建一个层级,并将 scope
和 service
都放置其中
- 真正的进程包含在
scope
或 service
中
- 在这一被划分层级的树中,每一个
slice
单位的名字对应通向层级中一个位置的路径
- 小横线(
-
)起分离路径组件的作用
- 可以像普通的 unit 一样被 systemd 管理,也可被
systemctl list-units
显示出来
- 本质上:启动一个以
systemd
进程为父进程的,干净的、独立的执行环境。默认在后台执行(也可通过 --no-block
或 --wait
选项定制)
- 默认情况下,
systemd-run
创建 simple
类型的临时服务,可以通过参数 --property=Type=exec
配置
- 若为
.path
、.socket
、.timer
单元,该单元会被立即启动
systemd-run --scope
用于创建一个新的 systemd 作用域(systemd scope
)来隔离程序的运行环境
- 在 systemd 中,
systemd scope
是一种资源控制单元,用于跟踪进程组的活动,并允许对它们进行管理
NAME
systemd-run - Run programs in transient scope units, service units, or path-, socket-, or timer-triggered
service units
SYNOPSIS
systemd-run [OPTIONS...] COMMAND [ARGS...]
systemd-run [OPTIONS...] [PATH OPTIONS...] {COMMAND} [ARGS...]
systemd-run [OPTIONS...] [SOCKET OPTIONS...] {COMMAND} [ARGS...]
systemd-run [OPTIONS...] [TIMER OPTIONS...] {COMMAND} [ARGS...]
参数说明:
--slice=<slice-name>
生成 cgroup 层级的名字
--unit=<name>
生成 unit 单元的名字
-p
限制资源信息
示例
记录 systemd 传递给服务单元的环境变量
$ systemd-run env
Running as unit: run-rfca9dba864cd40689ed91b8ae192a8c7.service
$ $ journalctl -u run-rfca9dba864cd40689ed91b8ae192a8c7.service
Apr 07 14:46:40 ip-172-31-38-208 systemd[1]: Started /usr/bin/env.
Apr 07 14:46:40 ip-172-31-38-208 env[438183]: LANG=C.UTF-8
Apr 07 14:46:40 ip-172-31-38-208 env[438183]: PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/>
Apr 07 14:46:40 ip-172-31-38-208 env[438183]: INVOCATION_ID=e283c29bdf9845c496ace0bb351dff67
Apr 07 14:46:40 ip-172-31-38-208 env[438183]: JOURNAL_STREAM=8:10454352
Apr 07 14:46:40 ip-172-31-38-208 env[438183]: SYSTEMD_EXEC_PID=438183
Apr 07 14:46:40 ip-172-31-38-208 systemd[1]: run-rfca9dba864cd40689ed91b8ae192a8c7.service: Deactivated successfully.
限制一个命令可以使用的资源
运行 updatedb
工具,并将其块设备 I/O
权重限制到 10
systemd-run -p BlockIOWeight=10 updatedb
特定时间运行命令
$ date; systemd-run --on-active=30 --timer-property=AccuracySec=100ms /bin/touch /tmp/foo
Sun Apr 7 02:49:09 PM UTC 2024
Running timer as unit: run-r904f7dd2409c4226a3a4a7cd6d30b64e.timer
Will run service as unit: run-r904f7dd2409c4226a3a4a7cd6d30b64e.service
$ journalctl -b -u run-r904f7dd2409c4226a3a4a7cd6d30b64e.timer
Apr 07 14:49:09 ip-172-31-38-208 systemd[1]: Started /bin/touch /tmp/foo.
$ journalctl -b -u run-r904f7dd2409c4226a3a4a7cd6d30b64e.timer
Apr 07 14:49:09 ip-172-31-38-208 systemd[1]: Started /bin/touch /tmp/foo.
$ journalctl -b -u run-r904f7dd2409c4226a3a4a7cd6d30b64e.service
Apr 07 14:49:39 ip-172-31-38-208 systemd[1]: Started /bin/touch /tmp/foo.
Apr 07 14:49:39 ip-172-31-38-208 systemd[1]: run-r904f7dd2409c4226a3a4a7cd6d30b64e.service: Deactivated successfully.
允许被运行的命令访问终端
以临时服务的方式运行 /bin/bash
命令, 并将其标准输入
、标准输出
、标准错误
连接到当前的 TTY
设备上
$ systemd-run -t --send-sighup /bin/bash
Running as unit: run-u166.service
Press ^] three times within 1s to disconnect TTY.
root@ip-172-31-38-208:/#
在一个临时的用户单元中运行 screen 工具
- 把
screen
作为 systemd --user
进程(由 user@.service
的某个实例启动)的子进程运行,并将其封装在一个临时 scope
单元中
- 使用
systemd.scope
单元而不是 systemd.service
单元,是因为 screen
会在脱离终端后退出,进而导致 service
单元被终结。将 screen
放在用户单元中运行,可以避免它成为会话 scope
单元的一部分
ubuntu@ip-172-31-38-208:~$ systemd-run --scope --user screen
Running scope as unit: run-ra297f1dd124e4e30a8bb7edfb6172fe4.scope
[detached from 438261.pts-0.ip-172-31-38-208]
cmd + A, cmd + D
ubuntu@ip-172-31-38-208:~$ screen -ls
There is a screen on:
438261.pts-0.ip-172-31-38-208 (04/07/2024 02:55:12 PM) (Detached)
1 Socket in /run/screen/S-ubuntu.
限制资源
# 指定 scope 作为前台进程存在的
systemd-run -p MemoryLimit=5M --unit=name --scope --slice=slice_name command
# 指定 scope 作为 .service 存在
systemd-run -p MemoryLimit=5M --unit=name --slice=slice_name command
# 命令执行完成后,创建的临时单元文件会自动清理
systemd-run -p MemoryLimit=5M -p CPUShares=100 --unit=sleep-10 --scope --slice=test sleep 10
# 将 bash 放入 service,限制其资源使用
# 使用 systemctl cat bash-limit.service 查看详情
# 使用 systemctl disable bash-limit.service --now 停止
systemd-run -p MemoryLimit=5M -p CPUShares=100 --unit=bash-limit --slice=bash-test -t /bin/bash