XENIAL-RECOVERY 是甚麼呢? 我在這個 Project 中使用 Arm 平台, 以 Nfs 開機, 復原 Ubuntu Xenial 16.04 作業系統. 請看下述 Youtube 影片: 


 
 

 

RamFs (InitRd / InitRamFs)

 

mkird 是本人寫的 script, 用途是製作 XENIAL-RECOVERY . 

 

# vi ./mkird

 

#!/bin/bash

RECOVERY=1
[ ! -f ./mkird ] && exit 1
[ ! -f ./prebuild/tarball/dev.tgz ] && exit 1

# Housekeeping...
CWD=`pwd`
rm -rf tmp/* boot/* ; mkdir -p tmp mnt boot

# Ramdisk Constants
RDSIZE=30000
BLKSIZE=1024

# Create an empty ramdisk image
dd if=/dev/zero of=tmp/ramdisk.img bs=$BLKSIZE count=$RDSIZE

# Make it an ext2 mountable file system
/sbin/mke2fs -L initrd -F -m 0 -b $BLKSIZE tmp/ramdisk.img $RDSIZE

# Mount it so that we can populate
#mount tmp/ramdisk.img mnt/initrd -t ext2 -o loop=/dev/loop0
#mount tmp/ramdisk.img mnt/initrd -t ext2 -o loop
mount tmp/ramdisk.img mnt/initrd -t ext2

mkdir -p mnt/initrd/bin mnt/initrd/etc mnt/initrd/proc mnt/initrd/sys mnt/initrd/dev mnt/initrd/etc/init.d mnt/initrd/var mnt/initrd/lib mnt/initrd/usr/lib
mkdir -p mnt/initrd/var/run mnt/initrd/etc/init.d mnt/initrd/mnt/initramfs mnt/initrd/mnt/sda1 mnt/initrd/mnt/sda2
mkdir -p mnt/initrd/mnt/tmp mnt/initrd/mnt/nfs mnt/initrd/mnt/rootfs mnt/initrd/mnt/asec
mkdir -p mnt/initrd/bin mnt/initrd/sbin mnt/initrd/lib

############################################################
#ls /opt/CodeSourcery/arm-none-linux-gnueabi/libc/lib/
make -C busybox ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- defconfig
make -C busybox ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
#make -C busybox ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install CONFIG_PREFIX=../mnt/initrd
make -C busybox ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install CONFIG_PREFIX=${CWD}/mnt/initrd
cd ${CWD}/e2fsprogs
LDFLAGS=-static ./configure --host=arm-none-linux-gnueabi --prefix=${CWD}/e2fsprogs/install
LDFLAGS=-static make V=1
rm -rf ${CWD}/e2fsprogs/install
MKFS_PATH=`find ${CWD}/e2fsprogs -name mke2fs`
#echo "MKFS_PATH=$MKFS_PATH"
/bin/cp -Rpf $MKFS_PATH ${CWD}/mnt/initrd/sbin/mkfs
cd ${CWD}

############################################################
/bin/cp -Rpf prebuild/bin/* mnt/initrd/bin/
/bin/cp -Rpf prebuild/sbin/netrecovery mnt/initrd/sbin/
/bin/cp -Rpf prebuild/etc/* mnt/initrd/etc/
[ $? -ne 0 ] && umount mnt/initrd && echo 'cannot copy ...' && exit 1
tar zxvf prebuild/tarball/dev.tgz -C mnt/initrd/dev/
[ $? -ne 0 ] && umount mnt/initrd && echo 'cannot copy ...' && exit 1
rm -rf mnt/initrd/lost+found
rm -rf mnt/initrd/dev/block/*
rm -rf mnt/initrd/dev/disk/*

############################################################
ls mnt/initrd/ && echo " "
ls mnt/initrd/bin/ && echo " "
ls mnt/initrd/sbin/ && echo " "
ls mnt/initrd/lib/ && echo " "
# netrecovery
if [ $RECOVERY -eq 1 ]; then
        sed -i s/^#netrecovery/netrecovery/g mnt/initrd/etc/init.d/rcS
else
        sed -i s/^netrecovery/#netrecovery/g mnt/initrd/etc/init.d/rcS
fi

############################################################
umount mnt/initrd
gzip -9 tmp/ramdisk.img
if [ $RECOVERY -eq 1 ]; then
        cp tmp/ramdisk.img.gz boot/recovery.img
else
        cp tmp/ramdisk.img.gz boot/ramfs.img
fi

 

dev.tgz 我就不詳述了 請自行 tar 起來, 或用 mknod 來製作. 
 

Cross 編譯 busybox & install 至 initrd, 差不多就是這樣....
make -C busybox ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- defconfig
make -C busybox ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- install CONFIG_PREFIX=${CWD}/mnt/initrd
....

Utility 的部分 我使用 esf2prog, 請注意它 Cross 的編譯方式
LDFLAGS=-static ./configure --host=arm-none-linux-gnueabi --prefix=${CWD}/e2fsprogs/install
LDFLAGS=-static make V=1
...

 

Prebuild 裡面的內容

 

# ls prebuild/
bin  etc  lib  sbin  tarball

# ls prebuild/tarball/
dev.tgz

# ls prebuild/bin/
busybox

# ls prebuild/sbin/
mke2fs  mkfs.ext2  mkfs.ext4  netrecovery

# ls prebuild/etc/
fstab  host.conf  hostname  hosts  ifplugd  inetd.conf  init.d  inittab  mke2fs.conf  network  nsswitch.conf  passwd  profile  resolv.conf  services  shells  shutdown  udhcpc.sh

# ls prebuild/lib/
root@monta:/home/arm-ubuntu/xenial-recovery-armhf
#

 

# cat prebuild/etc/fstab
proc            /proc      proc     defaults     0      0
devtmpfs        /dev       devtmpfs defaults     0      0
sysfs           /sys       sysfs    defaults     0      0

 

# cat prebuild/etc/host.conf
order hosts,bind
multi on

 

# cat prebuild/etc/hostname
monta

 

# cat prebuild/etc/hosts
127.0.0.1       localhost
127.0.1.1       monta

 

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

 

# cat prebuild/etc/ifplugd/ifplugd.action
#!/bin/sh

ifname="$1"
action="$2"

case "$action.$ifname" in
up.eth0)
        if [ -f /var/run/udhcpc.pid ]; then
               kill `cat /var/run/udhcpc.pid`
        fi
        /sbin/udhcpc -i eth0 -p /var/run/udhcpc.pid
        ;;
down.eth0)
        if [ -f /var/run/udhcpc.pid ]; then
               kill `cat /var/run/udhcpc.pid`
        fi
        ;;
esac

 

# cat prebuild/etc/inetd.conf
#telnet stream tcp nowait root /usr/sbin/telnetd telnetd -i

 

# cat prebuild/etc/inittab
::sysinit:/etc/init.d/rcS
#::askfirst:-/bin/sh

# Stuff to do when restarting the init process
::restart:/sbin/init

# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/etc/shutdown

# ttyAMA0
#::respawn:/sbin/inetd -f
::respawn:/sbin/getty 115200 ttyAMA0

 

# cat prebuild/etc/mke2fs.conf
[defaults]
        base_features = sparse_super,large_file,filetype,resize_inode,dir_index,ext_attr
        default_mntopts = acl,user_xattr
        enable_periodic_fsck = 0
        blocksize = 4096
        inode_size = 256
        inode_ratio = 16384

[fs_types]
        ext3 = {
                features = has_journal
        }
        ext4 = {
                features = has_journal,extent,huge_file,flex_bg,metadata_csum,64bit,dir_nlink,extra_isize
                inode_size = 256
        }
        ext4dev = {
                features = has_journal,extent,huge_file,flex_bg,metadata_csum,inline_data,64bit,dir_nlink,extra_isize
                inode_size = 256
                options = test_fs=1
        }
        small = {
                blocksize = 1024
                inode_size = 128
                inode_ratio = 4096
        }
        floppy = {
                blocksize = 1024
                inode_size = 128
                inode_ratio = 8192
        }
        big = {
                inode_ratio = 32768
        }
        huge = {
                inode_ratio = 65536
        }
        news = {
                inode_ratio = 4096
        }
        largefile = {
                inode_ratio = 1048576
                blocksize = -1
        }
        largefile4 = {
                inode_ratio = 4194304
                blocksize = -1
        }
        hurd = {
             blocksize = 4096
             inode_size = 128
        }

 

# cat prebuild/etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

 

# cat prebuild/etc/nsswitch.conf
passwd:     files
shadow:     files
group:      files

hosts:      files dns

protocols:  files
rpc:        files
services:   files

 

# cat prebuild/etc/passwd
root::0:0::/root:/bin/sh

 

# cat prebuild/etc/profile
# begin_generated_IBM_copyright_prolog
#
# This is an automatically generated copyright prolog.
# After initializing,  DO NOT MODIFY OR MOVE
# ================================================================
#
# Licensed Materials - Property of IBM
#
# Blue Gene/Q
#
# (C) Copyright IBM Corp.  2010, 2012
#
# US Government Users Restricted Rights -
# Use, duplication or disclosure restricted
# by GSA ADP Schedule Contract with IBM Corp.
#
# This software is available to you under the
# Eclipse Public License (EPL).
#
# ================================================================
#
# end_generated_IBM_copyright_prolog
export PATH=/sbin:/usr/sbin:$PATH

for i  in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "$PS1" ]; then
            . $i
        else
            . $i >/dev/null 2>&1
        fi
    fi
done

export LC_ALL=C

#. /etc/bg_profile

# root@q01i3j01 [Q01-I3-J01 10000]
#export PS1="\u@\h [$ASF_RANKNAME $ASF_COORDS]:\w # "

#export HOSTNAME=monta
#hostname $HOSTNAME
export PS1='$(whoami)@$(hostname):$(pwd)# '

 

# cat prebuild/etc/resolv.conf
nameserver 168.95.1.1

 

# cat prebuild/etc/services
# Network services, Internet style
#
# Note that it is presently the policy of IANA to assign a single well-known
# port number for both TCP and UDP; hence, officially ports have two entries
# even if the protocol doesn't support UDP operations.
#
# Updated from http://www.iana.org/assignments/port-numbers and other
# sources like http://www.freebsd.org/cgi/cvsweb.cgi/src/etc/services .
# New ports will be added on request if they have been officially assigned
# by IANA and used in the real-world or are needed by a debian package.
# If you need a huge list of used numbers please install the nmap package.

tcpmux          1/tcp                           # TCP port service multiplexer
echo            7/tcp
echo            7/udp
discard         9/tcp           sink null
discard         9/udp           sink null
systat          11/tcp          users
daytime         13/tcp
daytime         13/udp
netstat         15/tcp
...

 

# cat prebuild/etc/shells
/bin/sh
/bin/ash
/bin/hush

 

# cat prebuild/etc/shutdown
#!/bin/sh

true

 

# cat prebuild/etc/udhcpc.sh
#!/bin/sh

# udhcpc script edited by Tim Riker <Tim@Rikers.org>

[ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1

RESOLV_CONF="/etc/resolv.conf"
[ -n "$broadcast" ] && BROADCAST="broadcast $broadcast"
[ -n "$subnet" ] && NETMASK="netmask $subnet"

case "$1" in
  deconfig)
    /sbin/ifconfig $interface 0.0.0.0
    ;;

  renew|bound)
    /sbin/ifconfig $interface $ip $BROADCAST $NETMASK

    if [ -n "$router" ] ; then
      echo "deleting routers"
      while route del default gw 0.0.0.0 dev $interface ; do
        :
      done

      for i in $router ; do
        route add default gw $i dev $interface
      done
    fi

    echo -n > $RESOLV_CONF
    [ -n "$domain" ] && echo search $domain >> $RESOLV_CONF
    for i in $dns ; do
      echo adding dns $i
      echo nameserver $i >> $RESOLV_CONF
    done
    ;;
esac

exit 0

 

制定 rcS 開機 Script

 

把我們要做的事放入 rcS. netrecovery 劇本待會兒會提到. 在這兒把它以 # mark 起來, 就是 netboot

 

# vi prebuild/etc/init.d/rcS

 

#!/bin/sh

export HOSTNAME=monta
hostname monta

mkdir -p /etc/network/if-up.d
mkdir -p /etc/network/if-pre-up.d
mkdir -p /root
mkdir -p /sys
mkdir -p /proc
mkdir -p /tmp

mount -o remount,rw /
mount -t sysfs none /sys
mount -t tmpfs none /var
mkdir -p /var/log
mkdir -p /var/run
mount -t tmpfs none /dev
mount -t proc none /proc
echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s

# telnetd requires this
mkdir -p /dev/pts && mount -t devpts none /dev/pts
ln -sf /proc/mounts /etc/mtab

ip addr add 127.0.0.1/8 dev lo
ip link set lo up
ip link set eth0 up
#udhcpc -v -i eth0 -S -p /var/run/udhcpc.pid | grep 'Lease of ' | awk '{print $3}' | xargs ifconfig eth0
udhcpc -v -i eth0 -p /var/run/udhcpc.pid -S -s /etc/udhcpc.sh
[ $? -ne 0 ] && exit 0


###########################################################
###########################################################
netrecovery

exit 0

 

Netrecovery

 

# vi prebuild/sbin/netrecovery

 

#!/bin/sh

###########################################################
echo 'preparing recoverying ... '
sleep 3

###########################################################

NFS=`route | grep default | awk '{print $2}'`
mount -t nfs -o nolock,tcp ${NFS}:/tftpboot/xenial/netboot /mnt/tmp
#mount -t nfs -o nolock,tcp 10.100.11.12:/tftpboot/xenial/netboot /mnt/tmp
[ $? -ne 0 ] && exit 0
[ ! -f /mnt/tmp/rootfs.tgz ] && exit 0
[ ! -f /mnt/tmp/boot.tgz ] && exit 0

###########################################################
/bin/rm -rf /dev/sda /dev/sda1 /dev/sda2 /dev/sda5
mknod /dev/sda  b 8 0
mknod /dev/sda1 b 8 1
mknod /dev/sda2 b 8 2
mknod /dev/sda5 b 8 5

#echo 'fdisk ing ..., sda1='
dd if=/dev/zero of=/dev/sda bs=512 count=1
sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' << EOF | fdisk /dev/sda
 o
 n
 p
 1
 1
 +1024M
 n
 p
 2

 +51200M
 n
 e
 3

 +2048M
 n
 l


 t
 5
 82
 a
 1
 w
 q
EOF
[ $? -ne 0 ] && exit 0
fdisk -l /dev/sda

#mkswap --uuid 44546f01-0bd1-440c-bfa5-1e87bc7d254d -L swap /dev/sda5
mkswap -L swap /dev/sda5
[ $? -ne 0 ] && exit 0

#mkfs -t ext4 -F -U 9676373c-97a9-4278-ac24-3c854c434e98 -L rootfs /dev/sda2 -E lazy_itable_init
mkfs -t ext4 -F -U 9676373c-97a9-4278-ac24-3c854c434e98 -L rootfs /dev/sda2
[ $? -ne 0 ] && exit 0
mount -t ext4 /dev/sda2 /mnt/sda2
[ $? -ne 0 ] && exit 0
tar zxvf /mnt/tmp/rootfs.tgz -C /mnt/sda2
rm -rf /mnt/sda2/dev/block/*
rm -rf /mnt/sda2/dev/disk/*
rm -rf /mnt/sda2/lost+found
find /mnt/sda2/ -name .bash_history | xargs rm -rf

echo '###' > /mnt/sda2/etc/fstab
echo '#UUID=9676373c-97a9-4278-ac24-3c854c434e98 /               ext4    errors=remount-ro 0       1' >> /mnt/sda2/etc/fstab
echo '#UUID=7113ee79-3b3d-4e8e-8c16-fdb78f0d9c6f /boot           ext2    defaults          0       2' >> /mnt/sda2/etc/fstab
echo '/dev/sda2 /                                ext4    errors=remount-ro                 0       1' >> /mnt/sda2/etc/fstab
echo '/dev/sda1 /boot                            ext2    defaults                          0       2' >> /mnt/sda2/etc/fstab
echo '/dev/sda5 none                             swap    sw                                0       0' >> /mnt/sda2/etc/fstab

#sed -i s/^#\\/dev\\/sda2/\\/dev\\/sda2/ /mnt/sda2/etc/fstab
#sed -i s/^#\\/dev\\/sda1/\\/dev\\/sda1/ /mnt/sda2/etc/fstab
#sed -i s/^#\\/dev\\/sda5/\\/dev\\/sda5/ /mnt/sda2/etc/fstab

#mkfs -t ext2 -F -U 7113ee79-3b3d-4e8e-8c16-fdb78f0d9c6f -L boot /dev/sda1 -E lazy_itable_init
mkfs -t ext2 -F -U 7113ee79-3b3d-4e8e-8c16-fdb78f0d9c6f -L boot /dev/sda1
[ $? -ne 0 ] && exit 0
mount -t ext2 /dev/sda1 /mnt/sda1
[ $? -ne 0 ] && exit 0
tar zxvf /mnt/tmp/boot.tgz -C /mnt/sda1
rm -rf /mnt/sda1/lost+found

umount /mnt/tmp
umount /mnt/sda1
umount /mnt/sda2
sync ; sync ; sync
sync ; sync ; sync
sync ; sync ; sync
ls /

echo 'system recovery ok, rebooting now ...'
sleep 3 ; echo b > /proc/sysrq-trigger

 

下面提到的 boot.tgz 以及 rootfs.tgz 如何獲得? 請將正常開機的 Ubuntu ArmHf xenial /boot 以及 / TARBALL 起來. 

 

Pxe 設定檔案內容

 

# cat /tftpboot/pxelinux.cfg/default.xenial-recovery
LABEL xenial recovery
        KERNEL xenial/netinstall/vmlinuz
        APPEND initrd=xenial/netinstall/recovery.img console=ttyAMA0 init=/linuxrc root=/dev/ram0 rw noquiet

 

 

 


 

 

Try Deploy Ubuntu Boot I:

 

1. DETERMINE IF TRAGET ROOTFS IS MOUNT ON `/dev/sda1` , IF YES TRY THE FOLLOWING
2. COPY TARGET /boot/initrd*,vmlinuz*,System.map* to HOST /boot/ 不用覆蓋
3. BACKUP HOST /etc/default/grub , /boot/grub/grub.cfg
4. COPY TARGET /etc/default/grub to HOST /etc/default/grub
5. COPY /boot/grub/grub.cfg to HOST
6. EDIT the /etc/default/grub

IF /dev/sda1 is TARGET ROOTFS and TARGET vmlinuz-4.15.0-54-generic, initrd.img-4.15.0-54-generic
add the following to the first menuentry for /boot/grub/grub.cfg

menuentry 'Atgames' {
        recordfail
        load_video
        gfxmode $linux_gfx_mode
        insmod gzio
        if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
        insmod part_msdos
        insmod ext2
        set root='hd0,msdos1'
        linux   /boot/vmlinuz-4.15.0-54-generic root=/dev/sda1 ro
        initrd  /boot/initrd.img-4.15.0-54-generic
}
...

can MASK this line `set root='hd0,msdos1'` , I GUESS
vmlinuz-XXXX-generic initrd.img-XXXX-generic, refer to TARGET

7. update-grub -o ./grub.cfg
    ONLY GENERATE the ./grub.cfg, DON'T AFFECT THE HOST GRUB SETTING
8. COPY the ./grub.cfg to TARGET /boot/grub/grub.cfg
9. RESTORE the HOST /etc/default/grub from BACKUP
10. RESTORE the HOST /boot/grub/grub.cfg from BACKUP

 

 

Try Deploy Ubuntu Boot II:

 

$ cp initrd.img-4.15.0-54-generic ./initrd.gz
$ gunzip initrd.gz
$ mkdir -p rootfs
$ cd rootfs
$ cpio -id < ../initrd
$ mkdir -p mnt

 

EDIT the init

#!/bin/sh

export PATH=/sbin:/usr/sbin:/bin:/usr/bin
/bin/mount proc /proc -t proc
/bin/mount sysfs /sys -t sysfs
/bin/mount none /debug -t debugfs
mount -t ext2 /dev/sda1 /mnt

exec switch_root /mnt /sbin/init

 

$ sudo chmod +x ./init
$ sudo find . | cpio -o -H newc | gzip > ../initrd.gz
$ cd ..
$ cp initrd.gz initrd.img-4.15.0-54-generic

 

 

 

 

 

z.png
如果你覺得這篇文章對你有幫助, 請於留言板留個言, 以茲鼓勵. 謝謝! Email: jasonc@mail2000.com.tw

 

 

 

 

 

 

 

arrow
arrow

    Lexra 發表在 痞客邦 留言(0) 人氣()