OpenVZ如何启动OS?
How OpenVZ boot OS?
我购买了 VPS OpenVZ 虚拟化并启用了 Debian guest OS。
来宾 /boot
目录为空。 /etc/inittab
为空。
OS 初始化过程是如何执行的?
OpenVZ 容器的reboot
是什么意思?
一个 OpenVZ VPS 运行s,本质上,作为主机系统中的沙盒进程树。因此,它没有自己的引导加载程序或内核,并且通常 /boot
.
中没有任何文件
OpenVZ VPSes是在一个特殊的环境中让宿主系统运行 /bin/init
启动的,这样它就与宿主系统隔离开来,所以它相信本身是 PID 1。我不完全确定细节,因为 Parallels 没有详细记录它。
对于使用 systemd init 而不是 SysV init 的 Linux 系统来说,空的或丢失的 /etc/inittab
是正常的。当前版本的 Debian 默认使用 systemd;此行为并非特定于 OpenVZ。
我不完全确定 OpenVZ VPS 中的 运行ning reboot
是如何工作的,但我想主机内核必须对 reboot()
容器内的系统调用导致主机内核停止或重启容器,而不是整个系统。
经过研究,我克隆了 vzctl
工具作为主要工作 starting/stopping 在此处完成:
git clone https://github.com/OpenVZ/vzctl.git
git clone https://github.com/OpenVZ/libvzctl.git
vzctl
使用 libvzctl
可以找到 https://github.com/OpenVZ/libvzctl/blob/master/lib/env.c#L783:
int exec_init(struct start_param *param)
{
char cid[STR_SIZE];
char *argv[] = {"init", "-z", " ", NULL};
char *envp[] = {"HOME=/", "TERM=linux", cid, NULL};
char **env;
int errcode = 0;
logger(1, 0, "Starting init");
if (stat_file("/sbin/init") == 0 &&
stat_file("/ertc/init") == 0 &&
stat_file("/bin/init") == 0)
errcode = VZCTL_E_BAD_TMPL;
if (write(param->err_p[1], &errcode, sizeof(errcode)) == -1)
logger(-1, errno, "exec_init: write(param->err_p[1]");
snprintf(cid, sizeof(cid), "container="SYSTEMD_CTID_FMT, EID(param->h));
env = makeenv(envp, ¶m->h->env_param->misc->ve_env);
if (env == NULL)
return VZCTL_E_NOMEM;
execve("/sbin/init", argv, env);
execve("/etc/init", argv, env);
execve("/bin/init", argv, env);
free_ar_str(env);
free(env);
return VZCTL_E_BAD_TMPL;
}
停止由 https://github.com/OpenVZ/libvzctl/blob/master/lib/env.c#L103:
int real_env_stop(int stop_mode)
{
logger(10, 0, "* stop mode %d", stop_mode);
close_fds(1, -1);
/* Disable fsync. The fsync will be done by umount() */
configure_sysctl("/proc/sys/fs/fsync-enable", "0");
switch (stop_mode) {
case M_HALT: {
char *argv[] = {"halt", NULL};
char *argv_init[] = {"init", "0", NULL};
execvep(argv[0], argv, NULL);
execvep(argv_init[0], argv_init, NULL);
break;
}
case M_REBOOT: {
char *argv[] = {"reboot", NULL};
execvep(argv[0], argv, NULL);
break;
}
case M_KILL:
return syscall(__NR_reboot, LINUX_REBOOT_MAGIC1,
LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_POWER_OFF, NULL);
}
return -1;
}
在调用 /sbin/init
vzctl
之前进行一些检查(例如系统是否已经 运行 或挂载,是否存在一些文件等),如果需要则停止,挂载 fs,进行一些隔离模拟 chroot 并执行 /sbin/init
.
结论 OpenVZ 不使用来自来宾 OS 的 grub
/linux-image
/initrd
并直接调用首先在其中找到:
"/sbin/init"
"/etc/init"
"/bin/init"
在客人中OS。为了停止它使用
之一
halt
init 0
reboot
来自客人 OS。从用户的角度来看,容器初始化(安全、隔离、安装等)对来宾 OS 启动过程不感兴趣。
我购买了 VPS OpenVZ 虚拟化并启用了 Debian guest OS。
来宾 /boot
目录为空。 /etc/inittab
为空。
OS 初始化过程是如何执行的?
OpenVZ 容器的reboot
是什么意思?
一个 OpenVZ VPS 运行s,本质上,作为主机系统中的沙盒进程树。因此,它没有自己的引导加载程序或内核,并且通常 /boot
.
OpenVZ VPSes是在一个特殊的环境中让宿主系统运行 /bin/init
启动的,这样它就与宿主系统隔离开来,所以它相信本身是 PID 1。我不完全确定细节,因为 Parallels 没有详细记录它。
对于使用 systemd init 而不是 SysV init 的 Linux 系统来说,空的或丢失的 /etc/inittab
是正常的。当前版本的 Debian 默认使用 systemd;此行为并非特定于 OpenVZ。
我不完全确定 OpenVZ VPS 中的 运行ning reboot
是如何工作的,但我想主机内核必须对 reboot()
容器内的系统调用导致主机内核停止或重启容器,而不是整个系统。
经过研究,我克隆了 vzctl
工具作为主要工作 starting/stopping 在此处完成:
git clone https://github.com/OpenVZ/vzctl.git
git clone https://github.com/OpenVZ/libvzctl.git
vzctl
使用 libvzctl
可以找到 https://github.com/OpenVZ/libvzctl/blob/master/lib/env.c#L783:
int exec_init(struct start_param *param)
{
char cid[STR_SIZE];
char *argv[] = {"init", "-z", " ", NULL};
char *envp[] = {"HOME=/", "TERM=linux", cid, NULL};
char **env;
int errcode = 0;
logger(1, 0, "Starting init");
if (stat_file("/sbin/init") == 0 &&
stat_file("/ertc/init") == 0 &&
stat_file("/bin/init") == 0)
errcode = VZCTL_E_BAD_TMPL;
if (write(param->err_p[1], &errcode, sizeof(errcode)) == -1)
logger(-1, errno, "exec_init: write(param->err_p[1]");
snprintf(cid, sizeof(cid), "container="SYSTEMD_CTID_FMT, EID(param->h));
env = makeenv(envp, ¶m->h->env_param->misc->ve_env);
if (env == NULL)
return VZCTL_E_NOMEM;
execve("/sbin/init", argv, env);
execve("/etc/init", argv, env);
execve("/bin/init", argv, env);
free_ar_str(env);
free(env);
return VZCTL_E_BAD_TMPL;
}
停止由 https://github.com/OpenVZ/libvzctl/blob/master/lib/env.c#L103:
int real_env_stop(int stop_mode)
{
logger(10, 0, "* stop mode %d", stop_mode);
close_fds(1, -1);
/* Disable fsync. The fsync will be done by umount() */
configure_sysctl("/proc/sys/fs/fsync-enable", "0");
switch (stop_mode) {
case M_HALT: {
char *argv[] = {"halt", NULL};
char *argv_init[] = {"init", "0", NULL};
execvep(argv[0], argv, NULL);
execvep(argv_init[0], argv_init, NULL);
break;
}
case M_REBOOT: {
char *argv[] = {"reboot", NULL};
execvep(argv[0], argv, NULL);
break;
}
case M_KILL:
return syscall(__NR_reboot, LINUX_REBOOT_MAGIC1,
LINUX_REBOOT_MAGIC2,
LINUX_REBOOT_CMD_POWER_OFF, NULL);
}
return -1;
}
在调用 /sbin/init
vzctl
之前进行一些检查(例如系统是否已经 运行 或挂载,是否存在一些文件等),如果需要则停止,挂载 fs,进行一些隔离模拟 chroot 并执行 /sbin/init
.
结论 OpenVZ 不使用来自来宾 OS 的 grub
/linux-image
/initrd
并直接调用首先在其中找到:
"/sbin/init"
"/etc/init"
"/bin/init"
在客人中OS。为了停止它使用
之一halt
init 0
reboot
来自客人 OS。从用户的角度来看,容器初始化(安全、隔离、安装等)对来宾 OS 启动过程不感兴趣。