|
| 1 | + |
| 2 | +`systemd-run` 是一个非常强大的工具,它允许你将普通的命令封装成**临时的 (transient)** systemd 单元(Service、Scope 或 Timer)来运行。这对于后台运行任务、限制资源使用(CPU/内存)、定时执行以及与终端会话解绑非常有用。 |
| 3 | + |
| 4 | +--- |
| 5 | + |
| 6 | +### 🚀 1. 基础用法 |
| 7 | + |
| 8 | +最简单的用法,将命令作为后台服务运行(自动生成随机的 Unit 名称): |
| 9 | + |
| 10 | +```bash |
| 11 | +sudo systemd-run <command> [args...] |
| 12 | +# 示例: |
| 13 | +sudo systemd-run updatedb |
| 14 | +``` |
| 15 | + |
| 16 | +**在当前终端前台运行 (Scope 模式)** |
| 17 | +不放到后台,而是将其作为一个 Scope 运行(常用于对当前前台进程限制资源): |
| 18 | + |
| 19 | +```bash |
| 20 | +sudo systemd-run --scope <command> |
| 21 | +``` |
| 22 | + |
| 23 | +**打开一个完全隔离的交互式 Shell** |
| 24 | +分配伪终端 (PTY) 并且独立于当前登录会话(防止 SSH 断开导致任务终止): |
| 25 | + |
| 26 | +```bash |
| 27 | +sudo systemd-run --pty --same-dir -t /bin/bash |
| 28 | +``` |
| 29 | + |
| 30 | +--- |
| 31 | + |
| 32 | +### 🏷️ 2. 命名与描述 |
| 33 | + |
| 34 | +如果不指定名称,系统会生成类似 `run-r12345.service` 的名字。为了方便后续管理和查看日志,**强烈建议指定名称**。 |
| 35 | + |
| 36 | +```bash |
| 37 | +sudo systemd-run --unit=my-backup-task \ |
| 38 | + --description="Daily Database Backup" \ |
| 39 | + /usr/local/bin/backup.sh |
| 40 | +``` |
| 41 | + |
| 42 | +*执行后,你可以通过 `systemctl status my-backup-task` 来查看它。* |
| 43 | + |
| 44 | +--- |
| 45 | + |
| 46 | +### ⏳ 3. 阻塞等待与自动清理 |
| 47 | + |
| 48 | +默认情况下,`systemd-run` 会立即返回。如果你希望等待任务执行完毕,并获取其退出状态码: |
| 49 | + |
| 50 | +```bash |
| 51 | +# --wait 会阻塞当前终端,直到任务完成 |
| 52 | +sudo systemd-run --unit=my-task --wait /bin/sleep 5 |
| 53 | +``` |
| 54 | + |
| 55 | +如果加上 `--collect`,任务结束后对应的临时 unit 会被系统立即清理回收,不会在 `systemctl` 列表中留下处于 "dead" 状态的记录: |
| 56 | + |
| 57 | +```bash |
| 58 | +sudo systemd-run --collect --unit=my-task /bin/sleep 5 |
| 59 | +``` |
| 60 | + |
| 61 | +--- |
| 62 | + |
| 63 | +### 🛡️ 4. 资源限制 (Cgroups) |
| 64 | + |
| 65 | +这是 `systemd-run` 最强大的功能之一,利用 Cgroups 限制命令可使用的资源: |
| 66 | + |
| 67 | +**限制内存使用量 (超过将被 OOM 杀死):** |
| 68 | + |
| 69 | +```bash |
| 70 | +sudo systemd-run --scope -p MemoryMax=500M <command> |
| 71 | +``` |
| 72 | + |
| 73 | +**限制 CPU 使用率 (最高占用单核的 50%):** |
| 74 | + |
| 75 | +```bash |
| 76 | +sudo systemd-run --scope -p CPUQuota=50% <command> |
| 77 | +``` |
| 78 | + |
| 79 | +**限制 IO 权重 (降低后台任务对磁盘读写的影响):** |
| 80 | + |
| 81 | +```bash |
| 82 | +sudo systemd-run -p IOWeight=10 <command> |
| 83 | +``` |
| 84 | + |
| 85 | +*注:`-p` 是 `--property=` 的简写。* |
| 86 | + |
| 87 | +--- |
| 88 | + |
| 89 | +### ⏰ 5. 定时任务 (替代 Cron 或 at) |
| 90 | + |
| 91 | +`systemd-run` 可以即时创建临时的 timer unit。 |
| 92 | + |
| 93 | +**延迟执行 (类似 `at` 命令):** |
| 94 | + |
| 95 | +```bash |
| 96 | +# 5分钟后执行 |
| 97 | +sudo systemd-run --on-active="5m" --unit=delayed-job /bin/echo "Hello" |
| 98 | +``` |
| 99 | + |
| 100 | +**特定时间执行:** |
| 101 | + |
| 102 | +```bash |
| 103 | +# 在特定的时间点执行 |
| 104 | +sudo systemd-run --on-active="2024-12-31 23:59:00" /bin/echo "Happy New Year" |
| 105 | +``` |
| 106 | + |
| 107 | +**周期性执行 (类似 Cron):** |
| 108 | + |
| 109 | +```bash |
| 110 | +# 每天凌晨 2 点执行 |
| 111 | +sudo systemd-run --on-calendar="*-*-* 02:00:00" /usr/local/bin/daily-sync.sh |
| 112 | +``` |
| 113 | + |
| 114 | +--- |
| 115 | + |
| 116 | +### 👤 6. 用户与权限控制 |
| 117 | + |
| 118 | +**指定以特定系统用户身份运行:** |
| 119 | + |
| 120 | +```bash |
| 121 | +sudo systemd-run --uid=www-data --gid=www-data /bin/script.sh |
| 122 | +``` |
| 123 | + |
| 124 | +**作为普通用户运行(User systemd):** |
| 125 | +不需要 `sudo`,任务由用户的 systemd 实例管理(注销后只要启用了 lingering 也可以继续运行): |
| 126 | + |
| 127 | +```bash |
| 128 | +systemd-run --user --unit=my-user-task /bin/echo "Running as standard user" |
| 129 | +``` |
| 130 | + |
| 131 | +--- |
| 132 | + |
| 133 | +### 环境变量与工作目录 |
| 134 | + |
| 135 | +**设置环境变量:** |
| 136 | + |
| 137 | +```bash |
| 138 | +sudo systemd-run --setenv=FOO=bar --setenv=ENV=prod /bin/script.sh |
| 139 | +``` |
| 140 | + |
| 141 | +**指定工作目录:** |
| 142 | + |
| 143 | +```bash |
| 144 | +sudo systemd-run --working-directory=/var/www/html /bin/script.sh |
| 145 | +``` |
| 146 | + |
| 147 | +--- |
| 148 | + |
| 149 | +### 🔍 7. 管理与日志查看 |
| 150 | + |
| 151 | +假设你使用了 `--unit=my-task` 运行了一个任务: |
| 152 | + |
| 153 | +**查看状态:** |
| 154 | + |
| 155 | +```bash |
| 156 | +systemctl status my-task |
| 157 | +# 或者针对普通用户: |
| 158 | +systemctl --user status my-task |
| 159 | +``` |
| 160 | + |
| 161 | +**停止正在运行的任务:** |
| 162 | + |
| 163 | +```bash |
| 164 | +sudo systemctl stop my-task |
| 165 | +``` |
| 166 | + |
| 167 | +**查看任务的输出/日志:** |
| 168 | +systemd-run 运行的命令,其标准输出 (stdout) 和错误 (stderr) 会自动重定向到 Journal。 |
| 169 | + |
| 170 | +```bash |
| 171 | +# 查看该任务的所有日志 |
| 172 | +journalctl -u my-task |
| 173 | + |
| 174 | +# 持续滚动跟踪日志 |
| 175 | +journalctl -u my-task -f |
| 176 | +``` |
| 177 | + |
| 178 | +--- |
| 179 | + |
| 180 | +### 💡 实用组合技 (Pro Tips) |
| 181 | + |
| 182 | +**1. "防断网"后台下载(完美替代 `nohup ... &` 和 `tmux`):** |
| 183 | + |
| 184 | +```bash |
| 185 | +systemd-run --user --unit=download-ubuntu \ |
| 186 | + --remain-after-exit \ |
| 187 | + wget https://releases.ubuntu.com/22.04/ubuntu-22.04.4-desktop-amd64.iso |
| 188 | +``` |
| 189 | + |
| 190 | +*你可以随时关闭终端回家,之后只需运行 `journalctl --user -u download-ubuntu -f` 即可查看下载进度。* |
| 191 | + |
| 192 | +**2. 跑一个限制资源、指定目录和用户的后台脚本,并收集日志:** |
| 193 | + |
| 194 | +```bash |
| 195 | +sudo systemd-run --unit=heavy-data-process \ |
| 196 | + --working-directory=/data \ |
| 197 | + --uid=data_user \ |
| 198 | + -p CPUQuota=200% \ |
| 199 | + -p MemoryMax=4G \ |
| 200 | + python3 process.py |
| 201 | +``` |
0 commit comments