Skip to content

Instantly share code, notes, and snippets.

@rainly
Forked from diyism/session-setup-script.sh
Created October 17, 2019 00:07
Show Gist options
  • Save rainly/0c5bb5c075cfb014ddc8db36de60c8cf to your computer and use it in GitHub Desktop.
Save rainly/0c5bb5c075cfb014ddc8db36de60c8cf to your computer and use it in GitHub Desktop.
linux系统和应用目录都交错在一起了,用unionfs-fuse和pivot_root才能隔离,随系统启动:session-setup-script=session-setup-script.sh in /etc/lightdm/lightdm.conf @_:…boot+lib+(usr/)sbin+bin对SYS区,usr/(bin+lib+share)对APP区,etc+var公用
=================================pc lubuntu上, 2013年===========================================
#!/bin/sh
#chroot only for root user session
#pivot_root for whole system root directory changing
#sudo su
#mkdir /mnt/new_root #must be 755 root:root, or else sudo won't work: unable to stat /etc/sudoers: Permission denied
#mkdir /mnt/root #must be 755 root:root
#mkdir /mnt/rw #must be 755 root:root
#mkdir /mnt/rw/old_root #mkdir /media/malcolm/ext2/old_root
#root, rw, new root
mount --bind / /mnt/root
mount /dev/sda2 /mnt/rw #mount --bind /media/malcolm/ext2 /mnt/rw
unionfs-fuse -o cow,allow_other,use_ino,suid,dev,statfs_omit_ro,max_files=32768,chroot=/mnt /rw=RW:/root=RO /mnt/new_root
#unionfs改用overlayfs性能更好(ofs>aufs>ufs): mount -t overlayfs overlayfs -o lowerdir=/mnt/root,upperdir=/mnt/rw /mnt/new_root
#很多特殊fs类型的目录需要bind到新root(可以用df -aT看到所有的):
mount --bind /proc /mnt/new_root/proc
mount --bind /sys /mnt/new_root/sys
mount --bind /dev /mnt/new_root/dev
mount --bind /dev/pts /mnt/new_root/dev/pts
mount --bind /run /mnt/new_root/run #for google chrome etc
mount --bind /run/shm /mnt/new_root/run/shm #for google chrome etc
mount --bind /run/lock /mnt/new_root/run/lock #for google chrome etc
mount --bind /run/user /mnt/new_root/run/user #for google chrome etc
mount --bind /tmp /mnt/new_root/tmp #for x socket in /tmp/.X11-unix, used by python etc.
ln -s /home/malcolm/.Xauthority /mnt/new_root/home/malcolm/.Xauthority #for x session in .Xauthority
#pivot_root
/sbin/pivot_root /mnt/new_root /mnt/new_root/old_root #the $PATH in session-setup-script lack "/sbin"
exit 0 #return success
#还需要清理过程: https://gist.github.com/diyism/7872699
=================================pc kali上, 2018年===========================================
kali usb boot有选项"Live USB Encrypted Persistence" 或 "Live USB Persistence"可以直接实现相对于base iamge的变化写到指定的磁盘
=================================vps ubuntu上(digitalocean ubuntu 16.04 x64), 2018年==========
#ubuntu 14.04上没有overlayfs, ubuntu 18.04上的systemd-sysv没法用upstart-sysv替代掉, 而systemd无法在chroot(pivot_root)后使用,
#用不了switch_root, 因为switch_root后会导致目标overlay失效(别的overlay没影响), 看起来type是overlay实际已经退化到了/mnt/root
#switch_root /mnt/new_root /sbin/init
#还有个overlayroot的程序可以用另外一个分区作为overlay的upperdir, 但是不支持文件夹:
#http://blog.dustinkirkland.com/2012/08/introducing-overlayroot-overlayfs.html
#后述"4行代码超简类似docker容器"只能使用ubuntu 16.04的vps, 并且需要先执行命令:
#参考: http://without-systemd.org/wiki/index.php/How_to_remove_systemd_from_an_Ubuntu_Xenial_installation
apt-get install upstart-sysv -y
update-initramfs -u
#再到digitalocean网页switch off再switch on重启该vps后再ssh登录, 删除systemd:
apt-get remove --purge --auto-remove systemd #会删掉cgmanager,grub-pc-bin,liblxc1,libpam-systemd,lxc-common,lxd,policykit-1,snapd,systemd,systemd-shim,ubuntu-core-launcher
#给overlayfs及pivot_root准备挂载目录及脚本文件:
mkdir /mnt/rw #must be 755 root:root, or else sudo won't work: unable to stat /etc/sudoers: Permission denied
mkdir /mnt/rw/mnt && touch /mnt/rw/mnt/rw /mnt/rw/mnt/work /mnt/rw/mnt/new_root #阻止往从lowerdir继承来的4个空挂载点写入文件, 避免跟实际的下面两层layer混淆, 等pivot_root后实际的layer都在/old_root/mnt下
mkdir /mnt/rw/old_root #mount overlay后会挂载到/mnt/new_root/old_root
mkdir /mnt/work #must be 755 root:root
mkdir /mnt/new_root #must be 755 root:root
#cp /etc/init.d/rc.local /etc/init.d/rc.boot
#sed -i 's/\$all//' /etc/init.d/rc.boot
#sed -i 's/rc.local/rc.boot/g' /etc/init.d/rc.boot #digitalocean ubuntu 16.04 vps里/etc/rc2.d下是S02ssh,S03rc.local
#不能用把S03rc.local改成S00rc.local的方法, 因为upstart-sysv在安装新service时会重命名S##rc.local为最大序号
#ln -s ../init.d/rc.boot /etc/rc2.d/S01aaaarc.boot #抢在所有rc2.d之前执行overlay和pivot_root,比如抢在/etc/rc2.d/S02ssh之前,否则sshd进程还在旧root里
#不能用上面4行, 因为mountall.conf触发filesystem事件后, /etc/init/rc-sysinit.conf触发runlevel事件, 再触发/etc/init/ssh.conf和/etc/init/rc.conf,
#如果加/etc/rc2.d/S01aaaarc.boot, 只是保证在/etc/init/rc.conf内第一个执行, 无法保证抢在/etc/init/内其他十几个"runlevel 2"进程前执行, 只能:
echo $'description "rc.boot"\nemits pivoted\nstart on filesystem\ntask\nexec /etc/rc.boot' >/etc/init/rc.boot.conf
sed -i 's/filesystem and/filesystem and pivoted and/' /etc/init/rc-sysinit.conf
#可以用date +%s.%N && echo $$打印纳秒时间及进程id 以及 initctl list|grep process 来观察各个服务的先后启动次序
#注意上面的echo $'...\n...\n...'是bash命令, 后面用curl ...|sh执行时需要把那个"$"符号去掉
#用overlayfs+pivot_root实现简单类似docker容器:
#参考: http://cmp.felk.cvut.cz/~pisa/linux/init-overlay
#用nano /etc/rc.boot编辑文件, 重启vps后变成/old_root/etc/rc.boot:
#!/bin/sh -e
exec 2> /tmp/rc.boot.log # send stderr from rc.boot to a log file
exec 1>&2 # send stdout to the same log file
set -x # tell sh to display commands before execution
#4行代码实现超简类似docker容器:
/bin/mount -n -t overlay overlay -o lowerdir=/,upperdir=/mnt/rw,workdir=/mnt/work /mnt/new_root #加"-n"避免写入/etc/mtab
#注意在merge层或upperdir改过文件后lowerdir的变动就再也影响不到上层了
/bin/df -aT | /bin/grep -P -v "Type|ext4|overlay" | /usr/bin/awk '{print $7}' | /usr/bin/xargs -I {} /bin/mount --bind {} /mnt/new_root{} #pivot_root需要bind上旧的/proc, /sys, /dev, /run等等之后系统才能正常工作
/usr/bin/unshare -m & #不要该行的话, pivot_root时会报错pivot_root: failed to change root from `/mnt/new_root' to `/mnt/work': Invalid argument, 可以用grep -iP '/ /\s' /proc/$$/mountinfo 看变化
#不要该行的话, switch_root时会报错switch_root: failed to mount moving /dev to /mnt/new_root/dev: Invalid argument <\n> switch_root: forcing unmount of /dev
#另外需要结尾加"&"以及下行前加"sleep 2 &&", 否则/etc/rc.boot顶行的"-e"参数会退出
sleep 2 && /sbin/pivot_root /mnt/new_root /mnt/new_root/old_root
/sbin/initctl emit pivoted
exit 0
#然后:
chmod 755 /etc/rc.boot
#再到digitalocean网页switch off再switch on重启该vps后再ssh登录即可
#完成
===============最终简化为: 初始化digitalocean vps 16.04实现overlay容器:====================
apt-get install upstart-sysv -y && update-initramfs -u
#再到digitalocean网页switch off再switch on重启该vps后再ssh登录执行:
curl -sSfL https://git.io/fNtyS | sh
#再到digitalocean网页switch off再switch on重启该vps后再ssh登录即可
===============部署好nginx,php,mysql,业务代码等后, 备份rw层:====================
#ssh进入vps, 再执行:
cd /old_root/mnt/rw
tar -czpf ../rw.ki7j.tar.gz *
#本地机器上执行:
scp -P 22 root@<vps ip>:/old_root/mnt/rw.ki7j.tar.gz ./
===============在digitalocean或aws lightsail新建vps ubuntu 16.04并恢复rw层:====================
#先ssh登录并执行(lightsail需要先sudo su):
apt-get install upstart-sysv -y && update-initramfs -u
#再到digitalocean/aws lightsail网页switch off再switch on重启该vps后再ssh登录执行:
curl -sSfL https://git.io/fNtyS | sh
#不重启vps, 到本地机器执行(先cd /doc/vps_bak/, 另外在中国可能需要前缀proxychains scp ..., 在aws lightsail需要scp -i private.key ...):
scp -P 22 ./rw.ki7j.tar.gz root@<new vps ip>:/mnt/
#再到新vps里:
tar xzpf /mnt/rw.ki7j.tar.gz -C /mnt/rw/
#再到digitalocean/aws lightsail网页switch off再switch on重启该vps后再ssh登录(有可能rw层已改过ssh端口和密码/密钥)即可
#另外/old_root/etc/ssh/ssh_host_ecdsa_key.pub这个ssh客户端指纹等文件 是在pivot_root之前生成的base image层里, 没有备份到rw层, 导致恢复的新vps与旧vps略有差异
========================在digitalocean上装13MB的bargeOS再执行一行命令就可以替代上述overlayfs+pivot_root的方法:==========
https://gist.github.com/diyism/60aa6ca24df772a4928f1aced65e72ee
docker run -it --privileged=true --net=host ubuntu /bin/bash
如果想在docker里启动多个服务, 并且bash里exit时不影响container继续运行:
docker run -dit --privileged=true --net=host ubuntu /bin/multirun cmd1 cmd2 ...
docker exec -it con_id_first_few_chars /bin/bash
运行x11 gui程序:
docker run -it -e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix ubuntu cmd1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment