diff --git a/Makefile b/Makefile index 074ab78..98d6a89 100644 --- a/Makefile +++ b/Makefile @@ -27,10 +27,6 @@ install: cp images/* $(WORKSPACE)/images/ chown -R rocker:rocker $(WORKSPACE) - -mkdir /sys/fs/cgroup/rocker_1 - -mkdir /sys/fs/cgroup/rocker_2 - -mkdir /sys/fs/cgroup/rocker_3 - clean: -./target/debug/rocker --rm all -rocker --rm all diff --git a/src/cgroup.rs b/src/cgroup.rs index 0ed3d31..412473c 100644 --- a/src/cgroup.rs +++ b/src/cgroup.rs @@ -9,17 +9,29 @@ use crate::error::Result; static CGROUP_PATH: &str = "/sys/fs/cgroup/rocker"; pub enum CgroupLevel { - One, - Two, - Three, + V1, + V2, + V3, + V4, + V5, + V6, + V7, + V8, + V9, } impl From<&str> for CgroupLevel { fn from(value: &str) -> Self { match value { - "1" => CgroupLevel::One, - "2" => CgroupLevel::Two, - "3" => CgroupLevel::Three, + "v1" => CgroupLevel::V1, + "v2" => CgroupLevel::V2, + "v3" => CgroupLevel::V3, + "v4" => CgroupLevel::V4, + "v5" => CgroupLevel::V5, + "v6" => CgroupLevel::V6, + "v7" => CgroupLevel::V7, + "v8" => CgroupLevel::V8, + "v9" => CgroupLevel::V9, _ => todo!("invalid cgroup level"), } } @@ -28,16 +40,22 @@ impl From<&str> for CgroupLevel { impl Display for CgroupLevel { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - Self::One => write!(f, "1"), - Self::Two => write!(f, "2"), - Self::Three => write!(f, "3"), + Self::V1 => write!(f, "v1"), + Self::V2 => write!(f, "v2"), + Self::V3 => write!(f, "v3"), + Self::V4 => write!(f, "v4"), + Self::V5 => write!(f, "v5"), + Self::V6 => write!(f, "v6"), + Self::V7 => write!(f, "v7"), + Self::V8 => write!(f, "v8"), + Self::V9 => write!(f, "v9"), } } } impl Default for CgroupLevel { fn default() -> Self { - CgroupLevel::One + CgroupLevel::V1 } } diff --git a/src/main.rs b/src/main.rs index bdb8195..0238275 100644 --- a/src/main.rs +++ b/src/main.rs @@ -93,13 +93,6 @@ struct RockerArgs { cgroup: Option, } -macro_rules! rocker_println { - ($($arg:tt)*) => { - if cfg!(debug_assertions) { - println!($($arg)*); - } - }; -} /// 从images解压到volumes fn extend_image(image_name: &String) -> Result { @@ -217,11 +210,13 @@ fn init_container_custom_volume>(container_merged_path: P, custom Ok(()) } - -fn get_env_vec(env: &String) -> Result> { +fn clear_env() { for (k, _) in std::env::vars(){ std::env::remove_var(k); } +} + +fn get_env_vec(env: &String) -> Result> { let env_vec = if env.starts_with("./") || env.starts_with("/") { // 读取出路径指定的文件作为env let env_text = fs::read_to_string(env)?; @@ -301,7 +296,7 @@ fn init_container_pts() -> Result<()> { } fn init_container_log() -> Result<()> { - let log_path = Path::new("logs"); + let log_path = Path::new("/logs"); let log_file = fs::OpenOptions::new() .append(true) .write(true) @@ -362,15 +357,11 @@ fn create_pause(container_root_pause_path: &Path) -> Result<()> { fn start(container_info: &ContainerInfo, cb: CloneCb, clong_flags: CloneFlags, container_merged_pause_path: &PathBuf) -> Result<()>{ match unsafe {clone(cb, STACK.as_mut_slice(), clong_flags, None)} { Ok(child_pid) => { - { // 执行成功就保存吧~ - let mut _container_info = container_info.clone(); - _container_info.pid = child_pid.as_raw(); - let _ = _container_info.flush(); - } - // exec之前的步骤 create_network(&container_info.id, child_pid.as_raw()); - Cgroup::create(&container_info.id, child_pid.as_raw(), CgroupLevel::from(container_info.cgroup_level.as_str()))?; + if let Err(e) = Cgroup::create(&container_info.id, child_pid.as_raw(), CgroupLevel::from(container_info.cgroup_level.as_str())) { + println!("cgroup create error: {}", e) + } // 删除 pause标志文件, 解开阻塞, 使其执行exec (0..100).any(|i| { @@ -427,6 +418,8 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) - } else { return Err(RockerError::OtherError("容器工作目录创建失败".to_string())); } + // 保存容器信息 + let _ = container_info.flush(); let rocker_user_info = User::from_name(USER_NAME)?.ok_or(RockerError::OtherError(format!("没找到 用户: {USER_NAME}")))?; let rocker_uid = rocker_user_info.uid; @@ -434,7 +427,8 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) - let _cb = if let Some(exec_cmd) = is_exec_cmd { let _cb = || { - init_exec_ns(container_info.pid).unwrap(); + init_exec_ns(container_info.procs[0]).unwrap(); + clear_env(); let env_vec = get_env_vec(&Default::default()).unwrap(); if container_info.root == false { init_container_user(rocker_uid, rocker_gid).unwrap(); @@ -458,6 +452,7 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) - } else { let _cb = || { sethostname(USER_NAME).unwrap(); + clear_env(); let env_vec = get_env_vec(&container_info.env).unwrap(); let volume_path = extend_image(&container_info.image).unwrap(); @@ -479,7 +474,7 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) - // 挂载proc init_container_proc().unwrap(); - // + // 设置自定义env init_container_env(env_vec).unwrap(); // @@ -535,7 +530,6 @@ impl Display for ContainerStatus { #[derive(Deserialize, Serialize, Debug, Clone)] struct ContainerInfo { id: String, - pid: i32, status: ContainerStatus, run: String, // /bin/bash @@ -545,8 +539,9 @@ struct ContainerInfo { log: bool, wait: bool, root: bool, - - cgroup_level: String, // one/two/three + + cgroup_level: String, // v1/v2/v3... + procs: Vec // 动态从控制组中获取的 } impl ContainerInfo { @@ -564,7 +559,7 @@ impl Display for ContainerInfo { let env: String = self.env.chars().take(20).collect(); let run: String = self.run.chars().take(20).collect(); let image: String = self.image.chars().take(10).collect(); - write!(f, "\x1b[4m{:<10} {:<8} {:<10} {:<20} {:<20} {:<20} {:<10}\x1b[24m", self.id, self.pid, image, run, volume, env, &self.status) + write!(f, "\x1b[4m{:<10} {:<10} {:<20} {:<20} {:<20} {:<10}\x1b[24m", self.id, image, run, volume, env, &self.status) } } @@ -575,18 +570,10 @@ fn get_container_info(container_id: &str) -> Result { let mut container_info: ContainerInfo = toml::from_str(&info_str)?; // todo 判断当前进程组 是否还有进程 - let cgroup = Cgroup::from(&container_info); - - // 判断是否正在运行, 进入proc/pid/判断当前进程网络中是否有下面的设备 - // let dev_path = Path::new("/proc").join(container_info.pid.to_string()).join("net").join("dev"); - // let is_running = if let Ok(dev_text) = fs::read_to_string(dev_path){ - // let slave_veth_name = format!("ro_{container_id}_3"); - // dev_text.lines().any(|l|l.starts_with(&slave_veth_name)) - // } else { - // false - // }; - - if cgroup.procs.len() > 0 { + for pid in Cgroup::from(&container_info).procs { + container_info.procs.push(pid) + } + if container_info.procs.len() > 0 { container_info.status = ContainerStatus::RUNNING; } else { container_info.status = ContainerStatus::STOP; @@ -607,7 +594,7 @@ fn get_all_container_info() -> Result> { /// 读取所有容器的状态 fn show_containers(is_show_all: bool) -> Result<()> { - println!("{:<10} {:<8} {:<10} {:<20} {:<20} {:<20} {:<10}", "id", "pid", "image", "run", "volume", "env", "status"); + println!("{:<10} {:<10} {:<20} {:<20} {:<20} {:<10}", "id", "image", "run", "volume", "env", "status"); for container_info in get_all_container_info()? { if is_show_all{ println!("{container_info}"); @@ -686,7 +673,6 @@ fn stop_container(containers_id: &str, is_remove: bool) -> Result<()> { } } } - } Ok(()) } @@ -704,7 +690,6 @@ fn main() -> Result<()>{ (Some(cmd), Some(image), None) => { ContainerInfo { id: uuid::Uuid::new_v4().to_string()[0..8].to_string(), - pid: -1, run: cmd.clone(), image: image.clone(), volume: args.volume.clone().unwrap_or_default(), @@ -713,7 +698,8 @@ fn main() -> Result<()>{ log: args.log, wait: args.wait, cgroup_level: args.cgroup.clone().unwrap_or(CgroupLevel::default().to_string()), - root: args.root + root: args.root, + procs: vec![] } } (None, None, Some(_container_id)) => { @@ -761,6 +747,5 @@ fn main() -> Result<()>{ println!("容器{container_id}未运行"); } } - Ok(()) } \ No newline at end of file diff --git a/src/network.rs b/src/network.rs index b29f49d..aafa77e 100644 --- a/src/network.rs +++ b/src/network.rs @@ -122,7 +122,6 @@ fn del_dev(dev_name: &str) -> bool { return false; } } - true } diff --git a/test/test.py b/test/test.py index 49121e2..1b4ea03 100755 --- a/test/test.py +++ b/test/test.py @@ -8,6 +8,10 @@ import os import threading import ctypes +print("hello", time.time()) + +exit() + def read_memory(address): # 创建一个足够大的缓冲区来读取内存 buffer_size = 8 # 假设我们读取的是一个64位整数