如何在Rust中运行命令?执行nohup gdx-open ~/Documents &报错如何解决
Rust 执行 nohup 后台命令的正确方案
错误原因
你遇到的问题本质是:Command::new() 默认直接调用操作系统执行二进制程序,不会解析 shell 语法。你写的命令里的~路径展开、nohup的信号处理逻辑、&后台运行标记都是 shell 提供的功能,直接传给Command会被识别为非法参数,自然无法运行。
实现方案
方案1:显式调用 shell 执行(快速实现,适合可信输入场景)
如果不需要跨平台,且运行环境确定有bash,可以直接把整条命令作为shell的-c参数传入:
use std::process::Command; fn main() { // 不需要等待命令返回可以用 spawn() 代替 output() let _ = Command::new("bash") .arg("-c") .arg("nohup gdx-open ~/Documents &") .spawn() .expect("命令执行失败"); }
注意:该方案依赖目标环境存在bash,且如果命令参数包含用户输入的不可信内容,存在shell注入风险。
方案2:Rust 原生实现 nohup 效果(推荐,无额外依赖风险)
nohup + &的本质是实现三个效果:忽略终端挂断信号SIGHUP、脱离当前进程组后台运行、输入输出重定向到空或者日志文件。完全可以通过Rust的进程配置原生实现,不需要依赖shell和nohup:
- 先在
Cargo.toml添加依赖:
[dependencies] libc = "0.2" dirs = "5.0" # 用于兼容不同系统的HOME目录解析
- 代码实现:
use std::process::{Command, Stdio}; use std::os::unix::process::CommandExt; fn main() { let doc_path = dirs::home_dir() .expect("无法获取用户目录") .join("Documents"); let _child = Command::new("gdx-open") .arg(doc_path) // 重定向输入输出到空,对应nohup的默认行为 .stdin(Stdio::null()) .stdout(Stdio::null()) .stderr(Stdio::null()) // 脱离当前进程组 .process_group(0) // 忽略SIGHUP信号 .pre_exec(|| { unsafe { libc::signal(libc::SIGHUP, libc::SIG_IGN) }; Ok(()) }) .spawn() .expect("启动gdx-open失败"); // 此处可以继续执行主程序逻辑,不需要等待子进程退出 }
如果需要保留nohup日志,只需要把stdout和stderr的配置改为重定向到nohup.out文件即可。
内容的提问来源于stack exchange,提问作者MuchachoMop
相关产品推荐
相关产品推荐

