From 1ce123707684995b98217da0c1a6fc89711a6396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=B3=E5=85=89=E5=B0=91=E5=B9=B4?= <849317537@qq.com> Date: Wed, 7 Aug 2024 01:56:36 +0000 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90--stop=E5=92=8C--rm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.rs | 98 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 72 insertions(+), 26 deletions(-) diff --git a/src/main.rs b/src/main.rs index cef9f84..f2225f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,6 +37,8 @@ struct RockerArgs { image: Option, #[arg(long)] volume: Option, + #[arg(long)] + env: Option, #[arg(long)] log: bool, @@ -56,7 +58,12 @@ struct RockerArgs { // rm container_id #[arg(long)] - rm: Option + rm: Option, + + // stop container_id + #[arg(long)] + stop: Option + } @@ -276,21 +283,18 @@ fn check_container_is_running(pid: &Pid, main_exe: &Path) -> Result { let child_exe_path = Path::new(child_exe_s.as_str()); let target_child_exe_path = fs::read_link(child_exe_path)?; if target_child_exe_path != main_exe { - std::thread::sleep(std::time::Duration::from_millis(10)); return Ok(true); } - Ok(false) } -fn run_container(cmd: &String, args: &RockerArgs, volume_path: &PathBuf) -> Result<(String, i32)> { +fn run_container(_container_id: &String, cmd: &String, args: &RockerArgs, volume_path: &PathBuf) -> Result { // 禁止同时wait和log if args.wait && args.log { return Err(RockerError::OtherError("--wait/--log 禁止同时使用".to_string())); } // 初始化容器工作目录 - let _container_id = uuid::Uuid::new_v4().to_string()[0..8].to_string(); let container_work_path = Path::new(WORKSPACE).join("containers").join(&_container_id); let container_upper_path = container_work_path.join("upper"); let container_merged_path = container_work_path.join("merged"); @@ -315,7 +319,12 @@ fn run_container(cmd: &String, args: &RockerArgs, volume_path: &PathBuf) -> Resu init_container_user(rocker_uid, rocker_gid).unwrap(); let cmd_vec = parse_cmd(cmd); - execv(&cmd_vec[0], &cmd_vec).unwrap(); + match execv(&cmd_vec[0], &cmd_vec) { + Err(e) => { + println!("execv {cmd_vec:?}失败: {e:?}"); + } + _ => {}, + }; 0 }; @@ -326,10 +335,17 @@ fn run_container(cmd: &String, args: &RockerArgs, volume_path: &PathBuf) -> Resu println!("clone ok: {child_pid:?}"); // check_container_is_running + let mut cnt = 0; while let Ok(running) = check_container_is_running(&child_pid, &main_exe) { + cnt += 1; + std::thread::sleep(std::time::Duration::from_millis(10)); if running { break; } + if cnt > 1000 { + println!("{child_pid} 启动 超时"); + break; + } } // wait @@ -339,11 +355,11 @@ fn run_container(cmd: &String, args: &RockerArgs, volume_path: &PathBuf) -> Resu println!("{child_pid:?} exit: {status:?}"); } Err(e) => { - return Err(RockerError::OtherError(format!("{child_pid} err: {e}"))); + println!("{child_pid} wait err: {e}"); } } } - Ok((_container_id, child_pid.as_raw())) + Ok(child_pid.as_raw()) } Err(e) => { return Err(RockerError::OtherError(format!("clone err: {e}"))); @@ -398,7 +414,7 @@ fn save_container_info(args: &RockerArgs, container_id: &String, pid: i32) -> Re run: args.run.as_ref().unwrap().clone(), image: args.image.as_ref().unwrap().clone(), volume: args.volume.clone().unwrap_or("".to_string()), - env: "".to_string(), + env: args.env.clone().unwrap_or("".to_string()), status: ContainerStatus::READY, }; let toml_str = toml::to_string(&container_info)?; @@ -454,8 +470,8 @@ fn show_containers(is_show_all: bool) -> Result<()> { Ok(()) } -fn delete_container(containers_id: &str) -> Result<()> { - for container_id in containers_id.split(",") { +fn stop_container(containers_id: &str, is_remove: bool) -> Result<()> { + for container_id in containers_id.split(" ") { if let Ok(container_info) = get_container_info(container_id) { let container_work_path = Path::new(WORKSPACE).join("containers").join(container_id); let container_merged_path = container_work_path.join("merged"); @@ -463,24 +479,35 @@ fn delete_container(containers_id: &str) -> Result<()> { if container_info.status == ContainerStatus::RUNNING { kill(Pid::from_raw(container_info.pid), Signal::SIGTERM)?; } - // 卸载自定义挂载点 - let volumes_path = container_info.volume - .split(",") - .filter_map(|v| v.split(":").last()) - .map(|v| container_merged_path.join(v).to_string_lossy().to_string()) - .collect::>(); - for volume_path in volumes_path { - umount(volume_path.as_str())?; - println!("卸载卷: {volume_path:?}"); + if container_info.volume != "" { + container_info.volume + .split(",") + .filter_map(|v| v.split(":").last()) + .map(|v| container_merged_path.join(v).to_string_lossy().to_string()) + .for_each(|s| { + match umount(s.as_str()) { + Ok(s) => println!("卸载自定卷: {s:?}"), + Err(e) => panic!("卸载卷失败: {e:?}"), + } + }); } - // 卸载overlayfs - umount(container_merged_path.to_str().unwrap())?; + match umount(container_merged_path.to_str().unwrap()) { + Ok(s) => println!("卸载overlayfs卷: {s:?}"), + Err(e) => println!("卸载overlayfs失败: {e:?}"), + } + println!("停止容器: {container_id:?}"); // 删除容器目录 - fs::remove_dir_all(container_work_path)?; - println!("删除容器: {container_id:?}"); + if is_remove { + match fs::remove_dir_all(container_work_path) { + Ok(s) => println!("删除容器 {container_id} 成功"), + Err(e) => println!("删除容器失败: {e:?}"), + } + } + } else { + println!("容器不存在: {container_id}") } } @@ -493,15 +520,34 @@ fn main() -> Result<()>{ if let (Some(cmd), Some(image_name)) = (&args.run, &args.image) { // run let volume_path = extend_image(image_name)?; - let (container_id, pid) = run_container(cmd, &args, &volume_path)?; + let container_id = uuid::Uuid::new_v4().to_string()[0..8].to_string(); + let mut pid = -1; + match run_container(&container_id,&cmd, &args, &volume_path) { + Ok(child_pid) => { + pid = child_pid; + } + Err(e) => { + println!("run_container失败: {e}"); + } + } save_container_info(&args, &container_id, pid)?; // todo 无论出不错, 都要保存一个信息, 后面需要删除用清理 } else if args.ps || args.psa { // --ps show_containers(args.psa)? } else if let Some(containers_id) = &args.rm { // --rm - delete_container(containers_id)?; + stop_container(containers_id, true)?; + } else if let Some(containers_id) = &args.stop { + // --stop + stop_container(containers_id, false)?; } + // } else if let Some(containers_id) = &args.start { + // // --start + // start_container(containers_id)?; + // } else if let Some(containers_id) = &args.exec { + // // --exec + // exec_container(containers_id, &cmd, &args)?; + // } // exec