Skip to content

Ch 26: Command - 进程创建与管理

std::process::Command用于创建和管理外部进程,是Rust中执行系统命令的主要方式。

创建并执行简单命令:

use std::process::Command;
fn main() {
// 执行ls命令(Unix)或dir命令(Windows)
let output = Command::new("ls")
.arg("-la")
.output()
.expect("执行命令失败");
println!("标准输出: {}", String::from_utf8_lossy(&output.stdout));
println!("标准错误: {}", String::from_utf8_lossy(&output.stderr));
println!("退出码: {}", output.status);
}
impl Command {
pub fn new(program: &str) -> Command
// 参数相关
pub fn arg(&mut self, arg: &str) -> &mut Command
pub fn args<I, S>(&mut self, args: I) -> &mut Command
where I: IntoIterator<Item = S>, S: AsRef<OsStr>
// 环境相关
pub fn env(&mut self, key: &str, val: &str) -> &mut Command
pub fn env_remove(&mut self, key: &str) -> &mut Command
pub fn env_clear(&mut self) -> &mut Command
// 目录相关
pub fn current_dir(&mut self, dir: &Path) -> &mut Command
// 执行相关
pub fn output(&mut self) -> Result<Output>
pub fn status(&mut self) -> Result<ExitStatus>
pub fn spawn(&mut self) -> Result<Child>
}

spawn()创建子进程,不等待其完成:

use std::process::{Command, Stdio};
use std::io::Result;
fn main() -> Result<()> {
// 启动后台进程
let mut child = Command::new("sleep")
.arg("5")
.spawn()?;
println!("子进程PID: {}", child.id());
// 等待进程结束
let status = child.wait()?;
println!("进程退出码: {:?}", status);
Ok(())
}

返回的Child结构体:

pub struct Child {
pub id: u32,
pub stdin: Option<ChildStdin>,
pub stdout: Option<ChildStdout>,
pub stderr: Option<ChildStderr>,
}

output()等待命令完成并返回输出:

use std::process::Command;
fn main() {
// 获取命令输出
let output = Command::new("echo")
.arg("Hello from Rust!")
.output()
.expect("执行失败");
assert!(output.status.success());
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
}
use std::process::Command;
fn main() {
// 设置环境变量
let output = Command::new("printenv")
.arg("HOME")
.env("MY_VAR", "custom_value")
.output()
.expect("执行失败");
println!("{}", String::from_utf8_lossy(&output.stdout));
}
use std::process::Command;
use std::path::Path;
fn main() {
// 指定工作目录
let output = Command::new("pwd")
.current_dir("/tmp")
.output()
.expect("执行失败");
println!("{}", String::from_utf8_lossy(&output.stdout));
}
use std::process::{Command, Stdio};
use std::fs::File;
fn main() {
// 从文件读取输入
let input = File::open("input.txt").unwrap();
let output = Command::new("grep")
.arg("pattern")
.stdin(Stdio::from(input))
.output()
.expect("执行失败");
// 输出到文件
let mut file = File::create("output.txt").unwrap();
Command::new("ls")
.stdout(Stdio::from(file))
.spawn()
.expect("执行失败");
}

Stdio变体:

pub enum Stdio {
Inherited, // 继承父进程
Piped, // 管道
Null, // /dev/null
FromRaw(FileDesc), // 从文件描述符创建
}
use std::process::Command;
fn main() {
#[cfg(unix)]
{
// 以root身份运行
let output = Command::new("ls")
.arg("/root")
.uid(0) // root UID
.spawn()
.expect("需要root权限");
}
}

方法签名(Unix):

pub fn uid(&mut self, id: u32) -> &mut Command
pub fn gid(&mut self, id: u32) -> &mut Command
  1. 安全性:避免将未过滤的用户输入作为命令参数
  2. 错误处理:检查Result和status,子进程可能启动失败
  3. 僵尸进程:使用wait()确保子进程被回收
  4. shell注入:优先使用arg()而非通过shell执行复杂命令

Command是Rust中执行外部程序的核心API:

  • new() - 创建命令
  • arg() / args() - 添加参数
  • spawn() - 异步启动
  • output() - 同步执行并获取输出
  • status() - 同步执行并获取退出码

配合环境变量、目录和输入输出重定向,可以构建复杂的进程交互逻辑。