1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use std::process::Command;
/// Command-line tools
///
/// ```plain
/// Command::new(program):创建一个新的命令对象,program 是要执行的命令名称或路径
/// .arg(arg):添加命令参数
/// .args(args):添加多个命令参数(接收迭代器)
/// .output():执行命令并捕获输出(stdout/stderr)和退出状态
/// .status():执行命令并仅获取退出状态(输出直接传递给父进程)
/// .spawn():启动命令但不等待其完成(返回 Child 结构体,可手动控制)
/// .env(key, value):设置环境变量
/// .current_dir(path):设置命令执行的工作目录
/// ```
pub struct CmdUtil;
impl CmdUtil {
/// 运行命令
///
/// cmd: 数组方式的命令,第一个元素是命名执行程序
///
/// ```rust
/// use mitoo::CmdUtil;
///
/// CmdUtil::run_cmd(vec!["ffmpeg", "-i", "input.mp4", "output.mp4"])
/// ```
pub fn run_cmd(cmd: Vec<&str>) -> Result<String, String> {
if cmd.len() > 0 {
let full_command_line = cmd.join(" ").to_string();
let mut c = Command::new(cmd[0]);
if cmd.len() > 1 {
c.args(&cmd[1..]);
}
// 执行命令并捕获输出
let output = c.output().expect("请检查命令是否正确,或是否具备执行权限或环境变量等!");
// 处理命令执行结果
if output.status.success() {
println!("命令执行成功: \n{}", full_command_line);
// 可选:打印ffmpeg输出信息
let stdout = String::from_utf8_lossy(&output.stdout);
println!("命令输出:\n{}", stdout);
return Ok(stdout.to_string());
} else {
println!("命令执行失败: \n{}", full_command_line);
// 打印错误信息
let stderr = String::from_utf8_lossy(&output.stderr);
println!("错误信息:\n{}", stderr);
return Ok(stderr.to_string());
}
}
Err("没有命令".to_string())
}
/// TODO 未测试过
pub fn run_script(script_path: &str) -> std::io::Result<()> {
#[cfg(windows)]
let status = Command::new("cmd.exe")
.arg("/c")
.arg(script_path) // Windows 批处理脚本路径
.status()?;
#[cfg(not(windows))]
let status = Command::new("/bin/sh")
.arg(script_path) // Unix Shell 脚本路径
.status()?;
println!("脚本执行状态: {}", status);
Ok(())
}
/// TODO 未测试过
pub fn run_script_with_params(script_path: &str, params: Vec<&str>) -> std::io::Result<()> {
#[cfg(windows)]
let status = Command::new("cmd.exe")
.arg("/c")
.arg(script_path) // Windows 批处理脚本路径
.args(¶ms)
.status()?;
#[cfg(not(windows))]
let status = Command::new("/bin/sh")
.arg(script_path) // Unix Shell 脚本路径
.args(¶ms)
.status()?;
println!("脚本执行状态: {}", status);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_run_cmd() {
// 在 Windows 上使用 cmd.exe 执行 cd 命令
// let result = Command::new("cmd.exe")
// .arg("/c")
// .arg("cd /d D:/Environment && dir") // 可以追加其他命令查看效果
// .status()
// .expect("执行命令失败");
let cmd = vec!["cmd.exe", "/c", "cd", "/d", "d:/Environment/"];
let res = CmdUtil::run_cmd(cmd);
println!("{:?}", res);
let cmd = vec!["ffmpeg"];
let res = CmdUtil::run_cmd(cmd);
println!("{:?}", res);
}
}