use std::{fs, process};
use std::path::{Path, PathBuf};
use colored::Colorize;
use clap::{Arg, Command};
#[cfg(any(target_os = "macos", target_os = "linux"))]
use std::os::unix::fs::{OpenOptionsExt, PermissionsExt};
#[cfg(any(target_os = "macos", target_os = "linux"))]
use std::fs::{OpenOptions};
#[cfg(any(target_os = "macos", target_os = "linux"))]
use std::io::prelude::*;
use crate::ssh_module::command::{
impl_servers_table_action, impl_ssh_action,
import_get_servers_path_action,
import_set_servers_path_action,
};
pub fn get_home_dir() -> PathBuf {
let home_dir = match dirs::home_dir() {
None => {
eprintln!("\n[Aspen Error] => {} \n", "系统主目录获取失败".red(), );
process::exit(0);
}
Some(dir) => dir
};
home_dir
}
pub fn init_aspen() {
#[cfg(any(target_os = "macos", target_os = "linux"))]
{
let dir = env!("CARGO_PKG_NAME");
let shell_dir = format!("{}/{}/shell", get_home_dir().to_str().unwrap().to_string(), dir.to_string());
generate_folder(shell_dir.clone());
let controller_path = shell_dir.clone() + "/controller.sh";
// 要写入的内容
let controller_content = "#!/bin/bash\n\ncurrent_dir=$(dirname \"$(realpath \"$0\")\")\n\neval \"$(which expect) $current_dir/script.ex $1 $2 $3 $4 $5\"";
generate_shell(controller_path, controller_content);
let script_path = shell_dir.clone() + "/script.ex";
let script_content = "#!/usr/bin/expect\n\nset SERVER_NAME [lindex $argv 0]\nset IP [lindex $argv 1]\nset PORT [lindex $argv 2]\nset USER_NAME [lindex $argv 3]\nset PASSWORD [lindex $argv 4]\n\nspawn ssh -p $PORT $USER_NAME@$IP\n\nexpect {\n -timeout 300\n \"*assword\" { send \"$PASSWORD\\r\\n\"; exp_continue ; sleep 3; }\n \"yes/no\" { send yes\\n\"; exp_continue; }\n \"Last*\" {\n puts \"\\nLogin Successful!!!\\n\";\n }\n timeout { puts \"Expect was timeout.\"; return }\n}\n\ninteract\n";
generate_shell(script_path, script_content);
}
}
// 启动aspen命令
pub fn run() {
// 构建命令详情
let app = build_cli();
// 获取命令集合
let matches = app.get_matches();
match matches.subcommand() {
Some(("ssh", sub_matches)) => impl_ssh_action(sub_matches),
Some(("all", sub_matches)) => impl_servers_table_action(sub_matches),
Some(("set-path", sub_matches)) => import_set_servers_path_action(sub_matches),
Some(("get-path", sub_matches)) => import_get_servers_path_action(sub_matches),
_ => error_action(),
}
}
/**
* 构建命令
*/
pub fn build_cli() -> Command {
// 以Cargo.toml的版本为命令的版本号
let version = env!("CARGO_PKG_VERSION");
Command::new("aspen")
.name("Aspen Toolbox")
.version(version)
.author("Aspen Soung<songyang410@outlook.com>")
.about("Aspen工具箱")
.subcommand_required(true)
.arg_required_else_help(true)
// ssh工具箱
.subcommand(build_ssh_toolbox())
// 查看已配置的服务器列表
.subcommand(build_ssh_servers_table_toolbox())
// 设置服务器配置文件地址
.subcommand(build_set_servers_path_toolbox())
// 获取服务器配置文件地址
.subcommand(build_get_servers_path_toolbox())
}
// 构建ssh工具的命令
fn build_ssh_toolbox() -> Command {
Command::new("ssh")
.about("ssh工具箱")
.args([
Arg::new("index").help("输入服务器的 序号").required(false),
])
}
// 构建查看服务器列表命令
fn build_ssh_servers_table_toolbox() -> Command {
Command::new("all")
.about("查看已配置的服务器列表")
}
// 构建设置服务器配置地址命令
fn build_set_servers_path_toolbox() -> Command {
let about = format!("设置服务器的配置文件地址({})", "建议绝对地址".green());
Command::new("set-path")
.about(about)
.arg(Arg::new("path").help("请输入服务器配置文件地址(建议绝对地址)").required(true))
}
// 构建获取服务器配置地址命令
fn build_get_servers_path_toolbox() -> Command {
Command::new("get-path")
.about("获取服务器的配置文件地址")
}
fn error_action() {
eprintln!("\n[Aspen Error] => {} \n", "非法指令".red(), );
process::exit(0);
}
// 构建存储文件夹
pub fn generate_folder(folder_path: String) {
// 检查文件夹是否存在,如果不存在则创建
if !Path::new(&folder_path).exists() {
fs::create_dir_all(&folder_path).unwrap();
match fs::create_dir_all(&folder_path) {
Ok(_) => {}
Err(_) => {
eprintln!("\n[Aspen Error] => 创建文件夹 {} 失败! \n", folder_path.red(), );
process::exit(0);
}
}
#[cfg(any(target_os = "macos", target_os = "linux"))]
{
// 获取目标文件夹信息
let metadata = match fs::metadata(&folder_path) {
Ok(meta) => meta,
Err(_) => {
eprintln!("\n[Aspen Error] => 获取目标文件夹 {} 相关信息失败! \n", folder_path.red(), );
process::exit(0);
}
};
// 设置文件夹权限为 775
let mut permissions = metadata.permissions();
permissions.set_mode(0o775);
match fs::set_permissions(&folder_path, permissions) {
Ok(_) => {}
Err(_) => {
eprintln!("\n[Aspen Error] => 设置文件夹 {} 权限失败! \n", folder_path.red(), );
process::exit(0);
}
}
}
}
}
// 构建脚本
#[cfg(any(target_os = "macos", target_os = "linux"))]
fn generate_shell(file_path: String, content: &str) {
match fs::metadata(&file_path) {
Ok(_) => {}
Err(_) => {
// 创建文件并打开以进行写入,如果文件不存在则会创建它
let mut file = match OpenOptions::new()
.write(true)
.create(true)
.mode(0o775) // 设置权限为 775
.open(&file_path) {
Ok(file) => file,
Err(_) => {
eprintln!("\n[Aspen Error] => {} \n", "创建脚本失败".red(), );
process::exit(0);
}
};
// 将内容写入文件
match file.write_all(content.as_bytes()) {
Ok(_) => {}
Err(_) => {
eprintln!("\n[Aspen Error] => {} \n", "写入脚本内容失败!".red());
process::exit(0);
}
}
}
}
}