|
|
|
|
@ -1,9 +1,9 @@
|
|
|
|
|
use std::{io, fs, fmt, os, path, process, time};
|
|
|
|
|
use std::{io, fs, fmt, os, path, process, time, sync, thread, env};
|
|
|
|
|
use fmt::Display;
|
|
|
|
|
use os::fd::{AsFd, AsRawFd};
|
|
|
|
|
use os::unix::{fs::PermissionsExt, process::CommandExt};
|
|
|
|
|
use path::{Path, PathBuf};
|
|
|
|
|
use std::sync::OnceLock;
|
|
|
|
|
use sync::OnceLock;
|
|
|
|
|
|
|
|
|
|
use nix::sched::{clone, CloneCb, CloneFlags, setns};
|
|
|
|
|
use nix::sys::wait::{waitpid, WaitPidFlag};
|
|
|
|
|
@ -116,6 +116,7 @@ fn extend_image(image_name: &String) -> Result<PathBuf> {
|
|
|
|
|
let volume_path_str = volume_path.to_str().unwrap(); // 安全的unwrap
|
|
|
|
|
|
|
|
|
|
// 解压缩
|
|
|
|
|
println!("解压镜像: {image_name:?}");
|
|
|
|
|
let out = process::Command::new("tar")
|
|
|
|
|
.arg("-xvf")
|
|
|
|
|
.arg(image_path_str)
|
|
|
|
|
@ -134,7 +135,7 @@ fn extend_image(image_name: &String) -> Result<PathBuf> {
|
|
|
|
|
Ok(volume_path)
|
|
|
|
|
} else {
|
|
|
|
|
// 删除 volume_path
|
|
|
|
|
std::fs::remove_dir_all(volume_path)?;
|
|
|
|
|
fs::remove_dir_all(volume_path)?;
|
|
|
|
|
let std_err = String::from_utf8_lossy(&out.stderr);
|
|
|
|
|
Err(RockerError::from(io::Error::new(io::ErrorKind::Other, format!("解压缩镜像失败: {std_err}"))))
|
|
|
|
|
}
|
|
|
|
|
@ -218,8 +219,8 @@ fn init_container_custom_volume<P: AsRef<Path>>(container_merged_path: P, custom
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn clear_env() {
|
|
|
|
|
for (k, _) in std::env::vars(){
|
|
|
|
|
std::env::remove_var(k);
|
|
|
|
|
for (k, _) in env::vars(){
|
|
|
|
|
env::remove_var(k);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -238,7 +239,7 @@ fn init_container_env(env_vec: &Vec<String>) -> Result<()>{
|
|
|
|
|
for item_env in env_vec.iter() {
|
|
|
|
|
let item_env_v = item_env.split("=").collect::<Vec<&str>>();
|
|
|
|
|
if item_env_v.len() == 2 {
|
|
|
|
|
std::env::set_var(item_env_v[0], item_env_v[1])
|
|
|
|
|
env::set_var(item_env_v[0], item_env_v[1])
|
|
|
|
|
} else {
|
|
|
|
|
if item_env.len() > 0 {
|
|
|
|
|
println!("env 格式不正确: {item_env}")
|
|
|
|
|
@ -254,8 +255,8 @@ fn init_container_pivot<P: AsRef<Path>>(merged_path: P) -> Result<()> {
|
|
|
|
|
mount(None::<&str>, "/", None::<&str>, MsFlags::MS_PRIVATE | MsFlags::MS_REC, None::<&str>)?;
|
|
|
|
|
|
|
|
|
|
// 修改overlayfs 为rootfs
|
|
|
|
|
std::env::set_current_dir(merged_path)?;
|
|
|
|
|
let pwd_path = std::env::current_dir()?;
|
|
|
|
|
env::set_current_dir(merged_path)?;
|
|
|
|
|
let pwd_path = env::current_dir()?;
|
|
|
|
|
let pwd_str = pwd_path.to_string_lossy().to_string();
|
|
|
|
|
|
|
|
|
|
// 挂载bind todo
|
|
|
|
|
@ -269,11 +270,11 @@ fn init_container_pivot<P: AsRef<Path>>(merged_path: P) -> Result<()> {
|
|
|
|
|
pivot_root(pwd_str.as_str(), pivot_root_dir.as_str())?;
|
|
|
|
|
|
|
|
|
|
// 修改当前进程工作目录(注意我们之前已经到rootfs内, 并且把根目录设置完毕了)
|
|
|
|
|
std::env::set_current_dir("/")?;
|
|
|
|
|
env::set_current_dir("/")?;
|
|
|
|
|
|
|
|
|
|
// 卸载 old_root, 并删除临时文件
|
|
|
|
|
umount2(".pivot_root", MntFlags::MNT_DETACH).unwrap();
|
|
|
|
|
std::fs::remove_dir(".pivot_root").unwrap();
|
|
|
|
|
fs::remove_dir(".pivot_root").unwrap();
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -372,14 +373,14 @@ fn start(container_info: &ContainerInfo, cb: CloneCb, clong_flags: CloneFlags, c
|
|
|
|
|
|
|
|
|
|
// 删除 pause标志文件, 解开阻塞, 使其执行exec
|
|
|
|
|
(0..100).any(|i| {
|
|
|
|
|
std::thread::sleep(std::time::Duration::from_millis(i));
|
|
|
|
|
std::fs::remove_file(container_merged_pause_path).is_ok()
|
|
|
|
|
thread::sleep(time::Duration::from_millis(i));
|
|
|
|
|
fs::remove_file(container_merged_pause_path).is_ok()
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 检查是否执行exec了
|
|
|
|
|
let main_exe = std::env::current_exe()?;
|
|
|
|
|
let main_exe = env::current_exe()?;
|
|
|
|
|
for i in 0..100 {
|
|
|
|
|
std::thread::sleep(std::time::Duration::from_millis(i));
|
|
|
|
|
thread::sleep(time::Duration::from_millis(i));
|
|
|
|
|
if let Ok(true) = check_container_is_running(&child_pid, &main_exe) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@ -447,7 +448,7 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) -
|
|
|
|
|
init_container_env(&env_vec).unwrap();
|
|
|
|
|
create_pause(container_root_pause_path).unwrap();
|
|
|
|
|
while container_merged_pause_path.exists() {
|
|
|
|
|
std::thread::sleep(std::time::Duration::from_millis(10));
|
|
|
|
|
thread::sleep(time::Duration::from_millis(10));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let cmd_vec = exec_cmd.split(" ").collect::<Vec<&str>>();
|
|
|
|
|
@ -499,7 +500,7 @@ fn run_container(container_info: &ContainerInfo, is_exec_cmd: Option<&String>) -
|
|
|
|
|
// 暂停等待外部主进程设置网络设备
|
|
|
|
|
create_pause(&container_root_pause_path).unwrap();
|
|
|
|
|
while container_root_pause_path.exists() {
|
|
|
|
|
std::thread::sleep(std::time::Duration::from_millis(10));
|
|
|
|
|
thread::sleep(time::Duration::from_millis(10));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let cmd_vec = container_info.run.split(" ").collect::<Vec<&str>>();
|
|
|
|
|
@ -524,7 +525,7 @@ enum ContainerStatus {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Display for ContainerStatus {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
match self {
|
|
|
|
|
Self::READY => write!(f, "😀"),
|
|
|
|
|
Self::RUNNING => write!(f, "{Y}"),
|
|
|
|
|
@ -561,7 +562,7 @@ impl ContainerInfo {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Display for ContainerInfo {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
let volume: String = self.volume.chars().take(20).collect();
|
|
|
|
|
let env: String = self.env.chars().take(20).collect();
|
|
|
|
|
let run: String = self.run.chars().take(20).collect();
|
|
|
|
|
|