完成--stop和--rm

main
阳光少年 1 year ago
parent 4944cb2346
commit 1ce1237076

@ -37,6 +37,8 @@ struct RockerArgs {
image: Option<String>, image: Option<String>,
#[arg(long)] #[arg(long)]
volume: Option<String>, volume: Option<String>,
#[arg(long)]
env: Option<String>,
#[arg(long)] #[arg(long)]
log: bool, log: bool,
@ -56,7 +58,12 @@ struct RockerArgs {
// rm container_id // rm container_id
#[arg(long)] #[arg(long)]
rm: Option<String> rm: Option<String>,
// stop container_id
#[arg(long)]
stop: Option<String>
} }
@ -276,21 +283,18 @@ fn check_container_is_running(pid: &Pid, main_exe: &Path) -> Result<bool> {
let child_exe_path = Path::new(child_exe_s.as_str()); let child_exe_path = Path::new(child_exe_s.as_str());
let target_child_exe_path = fs::read_link(child_exe_path)?; let target_child_exe_path = fs::read_link(child_exe_path)?;
if target_child_exe_path != main_exe { if target_child_exe_path != main_exe {
std::thread::sleep(std::time::Duration::from_millis(10));
return Ok(true); return Ok(true);
} }
Ok(false) 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<i32> {
// 禁止同时wait和log // 禁止同时wait和log
if args.wait && args.log { if args.wait && args.log {
return Err(RockerError::OtherError("--wait/--log 禁止同时使用".to_string())); 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_work_path = Path::new(WORKSPACE).join("containers").join(&_container_id);
let container_upper_path = container_work_path.join("upper"); let container_upper_path = container_work_path.join("upper");
let container_merged_path = container_work_path.join("merged"); 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(); init_container_user(rocker_uid, rocker_gid).unwrap();
let cmd_vec = parse_cmd(cmd); 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 0
}; };
@ -326,10 +335,17 @@ fn run_container(cmd: &String, args: &RockerArgs, volume_path: &PathBuf) -> Resu
println!("clone ok: {child_pid:?}"); println!("clone ok: {child_pid:?}");
// check_container_is_running // check_container_is_running
let mut cnt = 0;
while let Ok(running) = check_container_is_running(&child_pid, &main_exe) { 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 { if running {
break; break;
} }
if cnt > 1000 {
println!("{child_pid} 启动 超时");
break;
}
} }
// wait // wait
@ -339,11 +355,11 @@ fn run_container(cmd: &String, args: &RockerArgs, volume_path: &PathBuf) -> Resu
println!("{child_pid:?} exit: {status:?}"); println!("{child_pid:?} exit: {status:?}");
} }
Err(e) => { 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) => { Err(e) => {
return Err(RockerError::OtherError(format!("clone 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(), run: args.run.as_ref().unwrap().clone(),
image: args.image.as_ref().unwrap().clone(), image: args.image.as_ref().unwrap().clone(),
volume: args.volume.clone().unwrap_or("".to_string()), volume: args.volume.clone().unwrap_or("".to_string()),
env: "".to_string(), env: args.env.clone().unwrap_or("".to_string()),
status: ContainerStatus::READY, status: ContainerStatus::READY,
}; };
let toml_str = toml::to_string(&container_info)?; let toml_str = toml::to_string(&container_info)?;
@ -454,8 +470,8 @@ fn show_containers(is_show_all: bool) -> Result<()> {
Ok(()) Ok(())
} }
fn delete_container(containers_id: &str) -> Result<()> { fn stop_container(containers_id: &str, is_remove: bool) -> Result<()> {
for container_id in containers_id.split(",") { for container_id in containers_id.split(" ") {
if let Ok(container_info) = get_container_info(container_id) { if let Ok(container_info) = get_container_info(container_id) {
let container_work_path = Path::new(WORKSPACE).join("containers").join(container_id); let container_work_path = Path::new(WORKSPACE).join("containers").join(container_id);
let container_merged_path = container_work_path.join("merged"); 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 { if container_info.status == ContainerStatus::RUNNING {
kill(Pid::from_raw(container_info.pid), Signal::SIGTERM)?; kill(Pid::from_raw(container_info.pid), Signal::SIGTERM)?;
} }
// 卸载自定义挂载点 // 卸载自定义挂载点
let volumes_path = container_info.volume if container_info.volume != "" {
container_info.volume
.split(",") .split(",")
.filter_map(|v| v.split(":").last()) .filter_map(|v| v.split(":").last())
.map(|v| container_merged_path.join(v).to_string_lossy().to_string()) .map(|v| container_merged_path.join(v).to_string_lossy().to_string())
.collect::<Vec<String>>(); .for_each(|s| {
for volume_path in volumes_path { match umount(s.as_str()) {
umount(volume_path.as_str())?; Ok(s) => println!("卸载自定卷: {s:?}"),
println!("卸载卷: {volume_path:?}"); Err(e) => panic!("卸载卷失败: {e:?}"),
}
});
} }
// 卸载overlayfs // 卸载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)?; if is_remove {
println!("删除容器: {container_id:?}"); 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) { if let (Some(cmd), Some(image_name)) = (&args.run, &args.image) {
// run // run
let volume_path = extend_image(image_name)?; 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 无论出不错, 都要保存一个信息, 后面需要删除用清理 save_container_info(&args, &container_id, pid)?; // todo 无论出不错, 都要保存一个信息, 后面需要删除用清理
} else if args.ps || args.psa { } else if args.ps || args.psa {
// --ps // --ps
show_containers(args.psa)? show_containers(args.psa)?
} else if let Some(containers_id) = &args.rm { } else if let Some(containers_id) = &args.rm {
// --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 // exec

Loading…
Cancel
Save