systemd-run 不支持直接运行交互式终端会话,但可通过预置输入、伪终端桥接或改造成准守护进程实现类服务化临时执行,兼顾资源控制、日志追踪与生命周期管理。

理解核心限制与替代思路
systemd-run 默认在非交互、无 TTY 的上下文中运行命令,所以 直接运行 read / bash -i / ssh -t 等依赖终端的脚本会失败或挂起。真正可行的做法是:把脚本改造成“准守护进程”——即剥离交互逻辑(如提前注入参数、用文件/管道传递输入),或用伪终端(pty)桥接(需额外工具)。临时服务的目标不是模拟 shell 交互,而是获得 systemd 的资源隔离、自动日志、依赖管理与优雅终止能力。
基础用法:封装无交互脚本为瞬态单元
假设你有一个无需键盘输入、只输出日志的脚本 /usr/local/bin/myscript.sh:
- 用
--scope启动一个带资源限制的临时作用域(推荐,轻量且可即时清理) - 添加
--collect让 unit 退出后仍保留最近日志供 journalctl 查看 - 指定 CPU/内存限制、工作目录、环境变量等
示例命令:
systemd-run --scope --collect \ --property=MemoryMax=200M \ --property=CPUQuota=50% \ --working-directory=/tmp \ --environment="DEBUG=1" \ /usr/local/bin/myscript.sh
执行后立即返回 unit 名(如 run-rf8a2b3c4d5e.scope),可用 systemctl status 或 journalctl -u 追踪。
处理“伪交互”需求:输入预置 + 输出捕获
若脚本内部有 read -p "Enter host:" HOST 这类语句,不要指望运行时敲键盘。正确做法是:
- 修改脚本,优先从环境变量或临时文件读取输入(兼容性更好)
- 用
echo "myhost" | systemd-run ... /usr/local/bin/myscript.sh配合脚本内read HOST || HOST=${HOST:-$(cat /dev/stdin)} - 或使用
--pipe(systemd ≥ 249)让 stdin/stdout/stderr 继承自当前终端 —— 仅适用于简单单次输入,不适用于多轮交互
例如:
echo "prod-db" | systemd-run --scope --pipe \ --property=Restart=no \ /bin/bash -c 'read host; echo "Connecting to $host..."; sleep 10'
高级:用 systemd-run 启动带 socket 激活或定时触发的临时服务
如果脚本需长期驻留、响应事件,可配合临时 socket 单元:
- 先用
systemd-run --scope --unit=mytemp@.service启动监听服务(需脚本支持 socket-activated 模式) - 或组合
systemd-run --on-active=30s实现延时启动,搭配--on-unit-active=...构建周期性临时任务 - 所有生成的 unit 默认在 reboot 后消失,符合“临时”要求
小技巧:加 --description="My ad-hoc backup" 方便识别;用 --uid/--gid 切换运行身份,避免权限问题。











