起因是,我偶尔看到 MediaWiki 导出时可以把图片也包含在 XML 文件中,但是不确定能不能顺利地导入回去。本来是准备拿虚拟机测试的,但是得在虚拟机里安装整套环境,麻烦呀。于是,结合前段时间折腾 Aufs 和 LXC 的经验,把当前正在运行的系统利用 Aufs 搞了一份只读挂载。当然还要弄个空目录来放可写分支:
mkdir -p root data sudo mount -t aufs -o br:$PWD/data=rw:/=ro aufs $PWD/root
其实这个样子就已经可以 chroot 进去跑 httpd 了。不过,得先改一下监听的端口,因为 chroot 环境与主系统只有文件系统是隔离的,网络空间还是共享的。chroot 中 PID 空间也是共享的,所以在里边杀进程时不小心把 PID 写错的话,是可能会把外边的进程给杀掉的……(而 LXC 中,主系统是可以杀容器中的进程,但是反过来不行,因为主系统中的进程在容器中根本没分配 PID。)
于是就来玩玩 LXC 啦。要注意把 fstab 删掉,不然 systemd 会不高兴。日志文件不能共享,否则 journald 会不高兴。因为把 mknod 权限给禁掉了,所以在容器里 loop 设备是没法创建的。如果需要,在主系统里 losetup 之后像注释里那样写一条挂载信息就好。
sudo rm root/etc/fstab sudo rm -r root/var/log/journal sudo mkdir root/var/log/journal sudo chgrp systemd-journal root/var/log/journal sudo brctl addbr br0 sudo ifconfig br0 192.168.10.1 cat > lxc.conf <<EOF lxc.utsname = arch2 lxc.autodev = 1 lxc.tty = 1 lxc.pts = 1024 lxc.rootfs = ${PWD}/root lxc.mount.entry = sysfs sys sysfs ro,defaults 0 0 lxc.mount.entry = proc proc proc nodev,noexec,nosuid 0 0 lxc.mount.entry = /proc/sys ${PWD}/root/proc/sys none ro,bind 0 0 lxc.cap.drop = mknod sys_module mac_admin mac_override # loop mount # lxc.mount.entry = /dev/loop1 /home/lilydjwg/tmpfs/root/var/lib/pacman ext4 rw 0 0 #networking lxc.network.type = veth lxc.network.link = br0 lxc.network.flags = up lxc.network.ipv4 = 192.168.10.3 lxc.network.name = eth0 #cgroups lxc.cgroup.devices.deny = a lxc.cgroup.devices.allow = c *:* m lxc.cgroup.devices.allow = b *:* m lxc.cgroup.devices.allow = c 1:3 rwm lxc.cgroup.devices.allow = c 1:5 rwm lxc.cgroup.devices.allow = c 1:7 rwm lxc.cgroup.devices.allow = c 1:8 rwm lxc.cgroup.devices.allow = c 1:9 rwm lxc.cgroup.devices.allow = c 1:9 rwm lxc.cgroup.devices.allow = c 4:1 rwm lxc.cgroup.devices.allow = c 5:0 rwm lxc.cgroup.devices.allow = c 5:1 rwm lxc.cgroup.devices.allow = c 5:2 rwm lxc.cgroup.devices.allow = c 136:* rwm EOF sudo lxc-start -n arch-dup -f lxc.conf
当然网络和 DNS 还要进去再设置一下:
route del -net 192.0.0.0/8 route add -net 192.168.0.0/16 eth0 route add -net default gw 192.168.10.1 echo 'nameserver 192.168.10.1' > /etc/resolve.conf
LXC 挺有点复杂的。systemd 的开发者也是这么认为的,所以他们搞了个操作便捷性类似于 chroot 但是功能类似于 LXC 的东东——systemd-nspawn!比如上边那个新系统可以这么启动:
sudo systemd-nspawn -b --private-network -D root
不过很遗憾的是,要么加--private-network
让新启动的容器没有网络,要么不加,和 chroot 一样与主系统共享网络。毕竟是他们用来测试 systemd 的东东嘛。调试系统的第一个进程可不容易,但是当它在另一个系统中只是一个普通进程、可以连 gdb 和 strace 时情况就大不一样啦 =w=
PS: 在 systemd-nspawn 的 manpage 中(上边那个 freedesktop.org 的链接),Arch 和 Fedora 以及 Debian 并列作为示例了呢 =w=
2015年3月14日更新:使用 Linux 3.18 及以上版本的内核,也可以使用 overlayfs 取代 aufs 来挂载,挂载命令示例如下:
modprobe overlay mount -t overlay -o lowerdir=/,upperdir=$PWD/.lxc-data,workdir=$PWD/.lxc-root overlayfs $PWD/.lxc-root
lowerdir
是只读的目录(其中的数据不会被修改),upperdir
是用于记录修改的可写目录,workdir
是工作目录,其必要性我也不理解,需要和upperdir
同一文件系统。我习惯上指定为挂载目标目录。
overlayfs 某些操作的效率似乎比 aufs 高不少。这里是我自己用来创建这个系统副本的 Shell 脚本。