使用rust执行shell命令,并调用go脚本将备份文件上传至阿里云OSS。
待完成:自动删除本地产生的备份文件。
use chrono::{Datelike, Local};
use regex::Regex;
use std::env;
use std::process::Command;
fn main() {
// 获取用户输入参数
let args: Vec<String> = env::args().collect();
// 校验用户是否输入参数
if args.len() < 3 || args.len() % 2 == 0 {
println!("{}", PrintColor::new("命令参数有误".to_string()).red());
help();
std::process::exit(1);
}
// 切换到指定目录工作
env::set_current_dir("/server/scripts/backup_to_oss").unwrap();
// 当前年月日
let local_time = Local::now();
let date = format!(
"{}-{}-{}",
local_time.year(),
local_time.month(),
local_time.day()
);
// 循环备份多个目录
for index in (1..args.len()).step_by(2) {
// if !args[index].ends_with(".zip") {
// println!(
// "{}",
// PrintColor::new("备份文件格式有误,以.zip结尾".to_string()).red()
// );
// return;
// }
if !is_file_path(args[index + 1].as_str()) {
println!("{}", PrintColor::new("路径格式有误".to_string()).red());
return;
}
// 执行备份操作
let file_zip = format!("{}_{}.zip", args[index].to_string(), date);
backup_to_oss(file_zip, args[index + 1].to_string())
}
}
fn backup_to_oss(file_zip: String, dir_path: String) {
// 当前目录
let current_path = env::current_dir().unwrap().to_string_lossy().to_string();
// println!("备份的文件名:{}", file_zip);
// println!("备份的目录:{}", dir_path);
let shell = format!("zip -r {} {}", file_zip, dir_path);
let shell = CMD::new(shell);
if !shell.command_bool() {
println!("{}", PrintColor::new("备份失败!".to_string()).red());
println!("备份文件: {}/{}", current_path, file_zip);
println!("失败目录: {}", dir_path);
return;
}
println!("{}", PrintColor::new("备份成功!".to_string()).green());
println!("备份文件: {}/{}", current_path, file_zip);
println!("备份目录: {}", dir_path);
// 上传至阿里云
let shell = format!("./go-oss web/{} {}", file_zip, file_zip);
let shell = CMD::new(shell);
if !shell.command_bool() {
println!("上传至阿里云失败: {}", file_zip);
return;
}
println!("上传至阿里云成功: {}", file_zip);
}
fn is_file_path(user_input: &str) -> bool {
let re = Regex::new(r"^/([^/]+/?)+$").unwrap();
return re.is_match(user_input);
}
// 打印帮助说明
fn help() {
println!(
"
{}
用法:backup_to_oss name1 dir_path1 name2 dir_path2
示例:backup_to_oss web_WEB-INF /www/html/web/WEB-INF web_r /www/html/web/r
说明:{}
",
PrintColor::new("文件备份至阿里云oss工具:".to_string()).yellow(),
PrintColor::new("仅适用于新航道运维项目组".to_string()).red()
)
}
struct CMD {
cmd: String, // 完整的shell命令
}
impl CMD {
fn new(cmd: String) -> CMD {
return CMD { cmd };
}
// 执行shell命令,获取执行结果与输出
#[allow(dead_code)]
fn command(&self) -> (String, bool) {
let shell = Command::new("sh")
.arg("-c")
.arg(&self.cmd)
.output()
.expect("命令执行失败");
if !shell.status.success() {
let stderr = format!("{}", String::from_utf8_lossy(&shell.stderr));
return (stderr, false);
}
let stdout = format!("{}", String::from_utf8_lossy(&shell.stdout));
return (stdout, true);
}
// 执行shell命令,获取执行输出
#[allow(dead_code)]
fn command_string(&self) -> String {
let shell = Command::new("sh")
.arg("-c")
.arg(&self.cmd)
.output()
.expect("命令执行失败");
if !shell.status.success() {
let stderr = format!("{}", String::from_utf8_lossy(&shell.stderr));
return stderr;
}
let stdout = format!("{}", String::from_utf8_lossy(&shell.stdout));
return stdout;
}
// 执行shell命令,只获取执行结果bool值
fn command_bool(&self) -> bool {
let shell = Command::new("sh")
.arg("-c")
.arg(&self.cmd)
.output()
.expect("命令执行失败");
return shell.status.success();
}
// 执行shell命令,获取实时输出
#[allow(dead_code)]
fn command_output(&self) {
println!("待完成")
}
}
// 输出带颜色字体
struct PrintColor {
msg: String,
}
impl PrintColor {
fn new(msg: String) -> PrintColor {
PrintColor { msg }
}
fn red(&self) -> String {
format!("\x1b[0;31m{}\x1b[0m", self.msg)
}
fn green(&self) -> String {
format!("\x1b[0;32m{}\x1b[0m", self.msg)
}
fn yellow(&self) -> String {
format!("\x1b[0;33m{}\x1b[0m", self.msg)
}
}本文发布于 upxos.com,著作权归 upX / upxos.com 所有。欢迎非商业场景转载或引用,请保留原文链接并注明出处;商业使用、改编发布或批量转载,请先联系 upX 获得书面授权。