阳光少年 1 year ago
parent 8b6762dab0
commit e3888c4996

@ -188,30 +188,20 @@ fn init_container_custom_volume<P: AsRef<Path>>(container_merged_path: P, custom
}
fn init_container_env(env: Option<&String>) -> Result<()>{
fn init_container_env(env: &String) -> Result<()>{
for (k, _) in std::env::vars(){
std::env::remove_var(k);
}
let env_vec = if let Some(env) = env {
let mut env_vec = if env.starts_with("./") || env.starts_with("/") {
// 读取出路径指定的文件作为env
let env_path = Path::new(env);
let mut env_file = fs::File::open(env_path)?;
let text = {
let mut s = String::new();
env_file.read_to_string(&mut s)?;
s
};
text.lines().map(String::from).collect::<Vec<String>>()
let env_text = fs::read_to_string(env)?;
env_text.lines().map(String::from).collect::<Vec<String>>()
} else {
env.split(",").map(String::from).collect::<Vec<String>>()
};
env_vec.push(r#"PS1=\u\h\W\$ "#.to_string());
env_vec
} else {
vec![r#"PS1=\u\h\W\$ "#.to_string()]
};
for item_env in env_vec.iter() {
let item_env_v = item_env.split("=").collect::<Vec<&str>>();
if item_env_v.len() == 2 {
@ -327,12 +317,17 @@ fn create_pause(container_root_pause_path: &Path) -> Result<()> {
Ok(())
}
fn start(is_wait: bool, cb: CloneCb, clong_flags: CloneFlags, container_id: &String, container_merged_pause_path: &PathBuf) -> Result<i32>{
fn start(container_info: &ContainerInfo, cb: CloneCb, clong_flags: CloneFlags, container_merged_pause_path: &PathBuf) -> Result<i32>{
match unsafe {clone(cb, STACK.as_mut_slice(), clong_flags, None)} {
Ok(child_pid) => {
println!("clone 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_id, child_pid.as_raw());
create_network(&container_info.id, child_pid.as_raw());
// 删除 pause标志文件, 解开阻塞, 使其执行exec
while std::fs::remove_file(container_merged_pause_path).is_err(){
std::thread::sleep(std::time::Duration::from_millis(10));
@ -355,7 +350,7 @@ fn start(is_wait: bool, cb: CloneCb, clong_flags: CloneFlags, container_id: &Str
println!("启动用时: {}ms", START_T.get().unwrap().elapsed().as_millis());
// wait
if is_wait {
if container_info.wait {
match waitpid(child_pid, Some(WaitPidFlag::WUNTRACED)) {
Ok(status) => {
println!("{child_pid:?} exit: {status:?}");
@ -368,66 +363,68 @@ fn start(is_wait: bool, cb: CloneCb, clong_flags: CloneFlags, container_id: &Str
Ok(child_pid.as_raw())
}
Err(e) => {
Err(RockerError::OtherError(format!("clone err: {e}")))
}
}
}
fn run_container(_container_id: &String, cmd: &String, args: &RockerArgs, volume_path: &PathBuf, is_exec: bool) -> Result<i32> {
fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) -> Result<i32> {
// 禁止同时wait和log
if args.wait && args.log {
if container_info.wait && container_info.log {
return Err(RockerError::OtherError("--wait/--log 禁止同时使用".to_string()));
}
let clone_flags;
let container_work_path = Path::new(WORKSPACE).join("containers").join(&_container_id);
let container_work_path = Path::new(WORKSPACE).join("containers").join(&container_info.id);
let container_upper_path = container_work_path.join("upper");
let container_merged_path = container_work_path.join("merged");
let container_merged_pause_path = container_work_path.join("merged").join("pause");
let container_root_pause_path = Path::new("/pause");
// 初始化容器工作目录
if create_dir(&container_work_path, true).is_ok() && create_dir(&container_upper_path, true).is_ok() && create_dir(&container_merged_path, true).is_ok() {
println!("容器工作目录创建成功");
} else {
return Err(RockerError::OtherError("容器工作目录创建失败".to_string()));
}
let rocker_user_info = User::from_name(USER_NAME)?.ok_or(RockerError::OtherError(format!("没找到 用户: {USER_NAME}")))?;
let rocker_uid = rocker_user_info.uid;
let rocker_gid = rocker_user_info.gid;
let _cb = if is_exec {
let _cb = if let Some(exec_cmd) = is_exec_cmd {
let _cb = || {
let container_info = get_container_info(_container_id).unwrap();
init_exec_ns(container_info.pid).unwrap();
init_container_env(None).unwrap();
init_container_env(&Default::default()).unwrap();
init_container_user(rocker_uid, rocker_gid).unwrap();
create_pause(container_root_pause_path).unwrap();
while container_merged_pause_path.exists() {
std::thread::sleep(std::time::Duration::from_millis(10));
}
let cmd_vec = cmd.split(" ").collect::<Vec<&str>>();
let cmd_vec = exec_cmd.split(" ").collect::<Vec<&str>>();
let err = process::Command::new(cmd_vec[0])
.args(&cmd_vec[1..])
.exec();
println!("execv {cmd_vec:?}失败: {err:?}");
0isize
};
clone_flags = CloneFlags::empty();
Box::new(_cb) as CloneCb
} else {
// 初始化容器工作目录
create_dir(&container_work_path, true)?;
create_dir(&container_upper_path, true)?;
create_dir(&container_merged_path, true)?;
let _cb = || {
init_container_overlay(volume_path, &container_upper_path, &container_merged_path).unwrap();
if let Some(custom_volume) = &args.volume {
init_container_custom_volume(&container_merged_path, custom_volume).unwrap();
let volume_path = extend_image(&container_info.image).unwrap();
init_container_overlay(&volume_path, &container_upper_path, &container_merged_path).unwrap();
if container_info.volume.len() > 3 { // .:. 最少也要有3个字符吧
init_container_custom_volume(&container_merged_path, &container_info.volume).unwrap();
}
sethostname(USER_NAME).unwrap();
init_container_env(args.env.as_ref()).unwrap();
init_container_env(&container_info.env).unwrap();
init_container_pivot(&container_merged_path).unwrap();
init_container_mount().unwrap();
init_container_log(args.log).unwrap();
init_container_log(container_info.log).unwrap();
init_container_user(rocker_uid, rocker_gid).unwrap();
create_pause(&container_root_pause_path).unwrap();
@ -435,7 +432,7 @@ fn run_container(_container_id: &String, cmd: &String, args: &RockerArgs, volume
std::thread::sleep(std::time::Duration::from_millis(10));
}
let cmd_vec = cmd.split(" ").collect::<Vec<&str>>();
let cmd_vec = container_info.run.split(" ").collect::<Vec<&str>>();
let err = process::Command::new(cmd_vec[0])
.args(&cmd_vec[1..])
.exec();
@ -446,10 +443,10 @@ fn run_container(_container_id: &String, cmd: &String, args: &RockerArgs, volume
Box::new(_cb) as CloneCb
};
start(args.wait, _cb, clone_flags, _container_id, &container_merged_pause_path)
start(container_info, _cb, clone_flags, &container_merged_pause_path)
}
#[derive(Deserialize, Serialize, Debug, PartialEq)]
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
enum ContainerStatus {
READY,
RUNNING,
@ -468,7 +465,7 @@ impl Display for ContainerStatus {
}
#[derive(Deserialize, Serialize, Debug)]
#[derive(Deserialize, Serialize, Debug, Clone)]
struct ContainerInfo {
id: String,
pid: i32,
@ -640,59 +637,38 @@ fn main() -> Result<()>{
let mut args = RockerArgs::parse();
if args.image.is_some() || args.restart.is_some() {
let volume_path;
let container_id;
let cmd;
match (&args.run, &args.image, &args.restart) {
(Some(_cmd), Some(image_name), None) => {
volume_path = extend_image(image_name)?;
container_id = uuid::Uuid::new_v4().to_string()[0..8].to_string();
cmd = _cmd.clone();
}
(None, None, Some(_container_id)) => {
let container_info = get_container_info(_container_id)?;
volume_path = extend_image(&container_info.image)?;
container_id = _container_id.clone();
cmd = container_info.run;
args.run = Some(cmd.clone());
args.image = Some(container_info.image);
args.log = container_info.log;
if container_info.volume.len() > 0 {
args.volume = Some(container_info.volume);
}
if container_info.env.len() > 0 {
args.env = Some(container_info.env);
}
stop_container(&container_id, false)?;
}
_ => {
unreachable!()
}
}
CONTAINER_INFO.get_or_init(||{
let container_info = match (&args.run, &args.image, &args.restart) {
(Some(cmd), Some(image), None) => {
ContainerInfo {
id: container_id.clone(),
id: uuid::Uuid::new_v4().to_string()[0..8].to_string(),
pid: -1,
run: args.run.as_ref().unwrap().clone(),
image: args.image.as_ref().unwrap().clone(),
run: cmd.clone(),
image: image.clone(),
volume: args.volume.clone().unwrap_or_default(),
env: args.env.clone().unwrap_or_default(),
status: ContainerStatus::READY,
log: args.log,
wait: args.wait
}
});
let container_info = CONTAINER_INFO.get().unwrap();
match run_container(&container_id, &cmd, &args, &volume_path, false) {
}
(None, None, Some(_container_id)) => {
stop_container(_container_id, false)?;
get_container_info(_container_id)?
}
_ => {
unreachable!()
}
};
match run_container(&container_info, None) {
Ok(child_pid) => {
// save_container_info(&args, &container_id, child_pid)?;
println!("容器 {} 启动成功, pid: {child_pid}", container_info.id);
}
Err(e) => {
// clone 之后的错误 这里已经无法捕获了
println!("run_container失败: {e}");
let is_remove = args.restart.is_none();
stop_container(&container_id, is_remove)?;
stop_container(&container_info.id, is_remove)?;
}
}
}
@ -707,7 +683,12 @@ fn main() -> Result<()>{
stop_container(containers_id, false)?;
} else if let (Some(cmd), Some(container_id)) = (&args.run, &args.exec) {
// --exec
run_container(container_id, &cmd, &args, &Default::default(), true).unwrap();
let container_info = get_container_info(container_id).unwrap();
if container_info.status == ContainerStatus::RUNNING {
run_container(&container_info, Some(cmd)).unwrap();
} else {
println!("容器{container_id}未运行");
}
}
Ok(())

@ -489,7 +489,7 @@ pub fn remove_network(uuid_name: &str) {
fn main(){
let container_id = uuid::Uuid::new_v4().to_string()[0..8].to_string();
// create_network(&container_id, 2084);
remove_network("c3a20664");
// remove_network("c3a20664");
}

Loading…
Cancel
Save