Rust系统退出码管理库sysexits的使用,提供标准化的Unix/C风格程序退出状态码常量定义
sysexits-rs
sysexits-rs (sysexits) 是一个提供系统退出码常量的库,这些常量定义在 <sysexits.h>
中。
该库实现了 Termination
trait,因此可以从 main
函数返回。
用法
在项目目录中运行以下命令:
cargo add sysexits
Crate 特性
extended_io_error
启用依赖于 io_error_inprogress
和 io_error_more
特性的功能。这也启用了 std
。nightly
隐含此特性。
nightly
启用依赖于夜间版 Rust 的功能。
std
启用依赖于标准库的功能。默认启用。
no_std
支持
支持 no_std
模式。禁用 default
特性以启用此功能。
文档
查看文档获取更多详细信息。
最低支持的 Rust 版本
该库的最低支持 Rust 版本 (MSRV) 是 v1.85.0。
源代码
上游仓库位于。
更新日志
请查看 CHANGELOG.adoc。
贡献
请查看 CONTRIBUTING.adoc。
许可证
版权所有 © 2022 Shun Sakai 和其他贡献者 (见 AUTHORS.adoc)
该库根据 Apache License 2.0 或 MIT License 的条款分发。
该项目符合 REUSE Specification 版本 3.3。有关版权和许可信息的更多详细信息,请参阅单个文件的版权声明。
完整示例代码
use sysexits::ExitCode;
fn main() -> Result<(), ExitCode> {
// 模拟一个成功操作
if some_operation_succeeds() {
Ok(())
} else {
// 返回标准化的退出码
Err(ExitCode::DataErr) // 表示输入数据有误
}
}
fn some_operation_succeeds() -> bool {
// 这里模拟操作逻辑
true // 或 false 来测试不同退出码
}
// 使用 Termination trait 的示例
fn main() -> ExitCode {
if some_operation_succeeds() {
ExitCode::Ok // 成功退出
} else {
ExitCode::Usage // 用法错误退出
}
}
// 直接使用常量值的示例
fn main() {
if some_operation_succeeds() {
std::process::exit(sysexits::EX_OK as i32); // 成功退出
} else {
std::process::exit(sysexits::EX_USAGE as i32); // 用法错误退出
}
}
完整示例代码:
use sysexits::ExitCode;
// 示例1: 使用 Result<(), ExitCode> 返回类型
fn main() -> Result<(), ExitCode> {
println!("程序开始执行...");
// 模拟数据处理操作
let data = vec![1, 2, 3];
if validate_data(&data) {
println!("数据处理成功");
Ok(())
} else {
println!("数据验证失败");
Err(ExitCode::DataErr) // 返回数据错误退出码
}
}
fn validate_data(data: &[i32]) -> bool {
// 简单的数据验证逻辑
!data.is_empty() && data.iter().all(|&x| x > 0)
}
// 示例2: 使用 Termination trait (直接返回 ExitCode)
fn main() -> ExitCode {
println!("检查系统配置...");
if check_system_config() {
println!("系统配置正常");
ExitCode::Ok // 成功退出
} else {
println!("系统配置错误");
ExitCode::Config // 配置错误退出
}
}
fn check_system_config() -> bool {
// 检查系统配置的逻辑
true
}
// 示例3: 直接使用常量值退出
fn main() {
println!("执行用户命令...");
match execute_user_command() {
Ok(_) => {
println!("命令执行成功");
std::process::exit(sysexits::EX_OK as i32)
},
Err(ErrorType::Usage) => {
println!("命令用法错误");
std::process::exit(sysexits::EX_USAGE as i32)
},
Err(ErrorType::Io) => {
println!("IO错误");
std::process::exit(sysexits::EX_IOERR as i32)
}
}
}
enum ErrorType {
Usage,
Io
}
fn execute_user_command() -> Result<(), ErrorType> {
// 模拟命令执行逻辑
Ok(())
}
1 回复
Rust系统退出码管理库sysexits使用指南
概述
sysexits库为Rust程序提供了标准化的Unix/C风格程序退出状态码常量定义,帮助开发者编写符合Unix惯例的命令行应用程序。
主要特性
- 提供符合sysexits.h标准的退出码常量
- 类型安全的ExitCode枚举
- 支持直接转换为std::process::ExitCode
- 清晰的错误分类和语义含义
安装方法
在Cargo.toml中添加依赖:
[dependencies]
sysexits = "0.3"
基本使用方法
1. 导入库
use sysexits::ExitCode;
use std::process;
2. 使用预定义退出码
fn main() {
// 成功退出
if everything_ok() {
process::exit(ExitCode::Ok.into());
}
// 命令行用法错误
if invalid_arguments() {
process::exit(ExitCode::Usage.into());
}
// 数据格式错误
if data_corrupted() {
process::exit(ExitCode::DataErr.into());
}
}
3. 完整示例
use sysexits::ExitCode;
use std::process;
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("Usage: {} <filename>", args[0]);
process::exit(ExitCode::Usage.into());
}
let filename = &args[1];
let content = match std::fs::read_to_string(filename) {
Ok(content) => content,
Err(e) => {
eprintln!("Cannot read file {}: {}", filename, e);
process::exit(ExitCode::NoInput.into());
}
};
if content.trim().is_empty() {
eprintln!("File is empty");
process::exit(ExitCode::DataErr.into());
}
println!("File content: {}", content);
process::exit(ExitCode::Ok.into());
}
完整示例demo
use sysexits::ExitCode;
use std::process;
use std::env;
use std::fs;
use std::io;
// 自定义错误处理函数
fn handle_file_operation(filename: &str) -> Result<String, ExitCode> {
// 检查文件是否存在
if !fs::metadata(filename).is_ok() {
eprintln!("错误:文件 '{}' 不存在", filename);
return Err(ExitCode::NoInput);
}
// 读取文件内容
let content = match fs::read_to_string(filename) {
Ok(content) => content,
Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {
eprintln!("错误:没有权限读取文件 '{}'", filename);
return Err(ExitCode::NoPerm);
}
Err(e) => {
eprintln!("错误:读取文件 '{}' 失败: {}", filename, e);
return Err(ExitCode::IoErr);
}
};
// 检查文件内容是否为空
if content.trim().is_empty() {
eprintln!("警告:文件 '{}' 内容为空", filename);
return Err(ExitCode::DataErr);
}
Ok(content)
}
// 处理命令行参数
fn parse_arguments(args: &[String]) -> Result<String, ExitCode> {
if args.len() != 2 {
eprintln!("用法:{} <文件名>", args[0]);
return Err(ExitCode::Usage);
}
Ok(args[1].clone())
}
fn main() {
// 获取命令行参数
let args: Vec<String> = env::args().collect();
// 解析参数
let filename = match parse_arguments(&args) {
Ok(filename) => filename,
Err(exit_code) => {
process::exit(exit_code.into());
}
};
// 处理文件操作
match handle_file_operation(&filename) {
Ok(content) => {
// 成功读取文件内容
println!("文件内容:\n{}", content);
process::exit(ExitCode::Ok.into());
}
Err(exit_code) => {
process::exit(exit_code.into());
}
}
}
// 单元测试
#[cfg(test)]
mod tests {
use super::*;
use std::fs::File;
use std::io::Write;
use tempfile::NamedTempFile;
#[test]
fn test_file_reading_success() {
let mut temp_file = NamedTempFile::new().unwrap();
writeln!(temp_file, "测试内容").unwrap();
let result = handle_file_operation(temp_file.path().to_str().unwrap());
assert!(result.is_ok());
}
#[test]
fn test_file_not_exists() {
let result = handle_file_operation("nonexistent_file.txt");
assert_eq!(result.err(), Some(ExitCode::NoInput));
}
}
常用退出码常量
常量 | 值 | 描述 |
---|---|---|
ExitCode::Ok |
0 | 程序成功执行 |
ExitCode::Usage |
64 | 命令行用法错误 |
ExitCode::DataErr |
65 | 输入数据错误 |
ExitCode::NoInput |
66 | 输入文件不存在或不可读 |
ExitCode::NoUser |
67 | 指定的用户不存在 |
ExitCode::NoHost |
68 | 指定的主机不存在 |
ExitCode::Unavailable |
69 | 服务不可用 |
ExitCode::Software |
70 | 内部软件错误 |
ExitCode::OsErr |
71 | 系统错误(无法创建文件等) |
ExitCode::OsFile |
72 | 关键系统文件不存在 |
ExitCode::CantCreat |
73 | 无法创建输出文件 |
ExitCode::IoErr |
74 | 输入/输出错误 |
ExitCode::TempFail |
75 | 临时故障,建议重试 |
ExitCode::Protocol |
76 | 远程协议错误 |
ExitCode::NoPerm |
77 | 权限不足 |
最佳实践
- 使用有意义的退出码:不要总是返回0或1,使用具体的错误代码
- 错误信息输出到stderr:将错误信息输出到标准错误流
- 文档说明:在程序文档中说明可能返回的退出码含义
注意事项
- 退出码范围应在0-255之间
- 退出码0始终表示成功
- 非零退出码表示不同程度的错误
- 遵循Unix惯例有助于脚本编写和自动化
通过使用sysexits库,您可以编写出更加专业和符合Unix惯例的命令行应用程序。