完成--stop和--rm

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

@ -37,6 +37,8 @@ struct RockerArgs {
image: Option<String>,
#[arg(long)]
volume: Option<String>,
#[arg(long)]
env: Option<String>,
#[arg(long)]
log: bool,
@ -56,7 +58,12 @@ struct RockerArgs {
// rm container_id
#[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 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<i32> {
// 禁止同时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
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())
.collect::<Vec<String>>();
for volume_path in volumes_path {
umount(volume_path.as_str())?;
println!("卸载卷: {volume_path:?}");
.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

Loading…
Cancel
Save