Rust编译的可执行文件全局运行时出现“No such file or directory”错误
问题原因
你遇到的问题是相对路径的解析基准错误:
- 在
/opt/motivate目录运行./motivate时,当前工作目录就是/opt/motivate,./data会被解析为/opt/motivate/data,能正确定位文件。 - 全局输入
motivate运行时,当前工作目录是你打开终端的目录(比如/home/yourname),程序会尝试读取/home/yourname/data,自然找不到目标文件,因此抛出"找不到文件"的错误。
解决方案
推荐通过获取可执行文件所在目录的方式构建data路径,这样无论在哪个目录运行程序,都能正确定位到依赖的data目录。
修改motivate函数的路径构建逻辑:
fn motivate() { let rand_filename = gen_rand(); // 获取可执行文件的绝对路径 let exe_path = std::env::current_exe().expect("Failed to get executable path"); // 提取可执行文件所在的目录 let exe_dir = exe_path.parent().expect("Failed to get executable directory"); // 拼接出目标文件的完整路径 let quotes_path = exe_dir.join("data").join(format!("{}.json", rand_filename)); // 读取文件内容 let file_contents_result = fs::read_to_string("es_path); match file_contents_result { Ok(file_contents) => { // 直接反序列化为目标类型,无需先转成Value match serde_json::from_str::<Vec<Quote>>(&file_contents) { Ok(quotes) => get_quotes(quotes), Err(err) => eprintln!("Error parsing JSON: {}", err), } } Err(err) => { eprintln!("Error reading file: {}", err); } } }
额外代码改进建议
替换
unwrap(),避免程序崩溃:
原代码中serde_json::from_str(&file_contents).unwrap()会在JSON解析失败时直接panic,换成match或if let处理错误,能让程序更健壮。直接反序列化为目标类型:
无需先解析成Value,可以直接反序列化为Vec<Quote>(假设JSON文件是Quote对象数组),代码更简洁且类型更安全。优化错误处理流程:
可以用?操作符简化错误传递,需要将motivate函数的返回类型改为Result<(), Box<dyn std::error::Error>>,让错误处理更简洁:fn motivate() -> Result<(), Box<dyn std::error::Error>> { let rand_filename = gen_rand(); let exe_path = std::env::current_exe()?; let exe_dir = exe_path.parent().ok_or("Failed to get executable directory")?; let quotes_path = exe_dir.join("data").join(format!("{}.json", rand_filename)); let file_contents = fs::read_to_string("es_path)?; let quotes: Vec<Quote> = serde_json::from_str(&file_contents)?; get_quotes(quotes); Ok(()) } fn main() { if let Err(err) = motivate() { eprintln!("Error: {}", err); std::process::exit(1); } }校验文件存在性:
如果gen_rand()生成的文件名可能不存在,建议在读取前先检查文件是否存在,提前给出更明确的错误提示。
内容的提问来源于stack exchange,提问作者John Philip
相关产品推荐
相关产品推荐

