备份/克隆活动系统到一个可以启动的新分区

Ubuntu 18.04于2018年4月26日发布,我想尝试升级我的程序并转换我的数据,但如果存在错误,我不想承诺。
我已将Windows从410 GB缩小到385 GB,重新启动了Ubuntu 16.04,并运行了gparted来创建一个新的25 GB分区,标记为"Ubuntu18.04"。我运行了rm-kernels并删除了大约20个内核,以在Ubuntu 16.04上节省约10 GB的空间。
现在我想要一个脚本,可以将新分区填充为16.04 LTS,并为其创建一个新的Grub菜单选项。只有相关的目录应该被复制。例如,/sys、/run、/proc和/dev是在启动时创建的虚拟目录,不应该被复制。
我还希望通过正确的UUID修补/etc/fstab,并禁用cron重启任务,以便在克隆数据启动后不再运行每日备份。
我预计在接下来的几周/几个月内多次运行该脚本。因此,克隆过程应该能够轻松重复。
同样的脚本可以用于测试安全更新和新的Ubuntu内核团队更新,而不会影响生产系统。

20个内核占用10GB!?你是不是误装了内核臃肿版? - Lie Ryan
@LieRyan 实际上每个内核占用的空间是400MB,而不是我四舍五入后的500MB(大约20个内核)。要查看每个内核占用的空间(在我的当前安装中波动在394MB到419MB之间),请参考:https://askubuntu.com/questions/949411/how-to-determine-obsolete-kernels-and-remove-them-to-clean-up-disk-space/949621#949621 - WinEunuuchs2Unix
2个回答

将活动的Ubuntu分区克隆到克隆分区的Bash脚本

clone-ubuntu.sh Bash脚本可以无缝且安全地复制16.04 LTS并升级到18.04 LTS的分区:

clone-ubuntu.png

重要考虑事项:
  • 你必须创建一个足够大的空的ext4分区来容纳一个Ubuntu 16.04克隆
  • 在调用脚本clone-ubuntu.sh时,分区不能被挂载。脚本会自动挂载和卸载分区。
  • 使用命令rsync将文件从/复制到克隆分区。第一次运行clone-ubuntu.sh需要几分钟。第二次运行脚本时,只有文件更改会被更新,所以应该只需不到一分钟。
  • 您可能会多次运行此脚本并重新启动。为了与当前的/文件和目录保持一致,克隆目标上的任何新数据都将被删除
  • 所有Cron /etc/cron.d(重启)作业都被移动到一个名为/etc/cron.d/hold的新子目录中。在启动克隆后,请记得运行sudo crontab -e以防止选定的cron作业运行。
  • 克隆文件/etc/fstab被修改为适当的分区UUID。
  • 克隆文件/boot/grub/grub.cfg被修改为适当的UUID以实现成功克隆引导。克隆文件的quiet splash被更改为nosplash,这样您就可以看到滚动的终端消息。这样可以在引导克隆而不是"真实"版本时获得视觉感知。
  • 运行update-grub以使用指向克隆分区的新菜单选项更新Grub。
  • 克隆文件/etc/update-manager/release-upgrades被修改为将Prompt=never更改为Prompt=lts。当您启动克隆并执行do-release-upgrade -d时,这将允许将Ubuntu 16.04升级到18.04。
  • 在克隆之前,会显示一个确认屏幕(在下一部分中显示),您必须输入y/Y才能继续。

确认屏幕

在选择目标克隆分区后,首先会验证其是否为ext4分区类型,并且尚未挂载。如果通过了这个测试,将出现一个确认消息:

=====================================================================
Mounting clone partition /dev/nvme0n1p8 as /mnt/clone16.04

=====================================================================
PLEASE: Carefully confirm Source (Live) and Target (Clone) partitions

SOURCE (BOOT /):  /dev/nvme0n1p5      TARGET (CLONE):  /dev/nvme0n1p8
ID:               Ubuntu              ID:              Ubuntu
RELEASE:          16.04               RELEASE:         16.04
CODENAME:         xenial              CODENAME:        xenial
DESCRIPTION:      Ubuntu 16.04.3 LTS  DESCRIPTION:     Ubuntu 16.04.3 LTS
 Size  Used Avail Use%                 Size  Used Avail Use%
  44G   17G   26G  40%                  24G   17G  5.8G  74%

NOTE: If you are recloning, new files in clone will be deleted,
      modified files are reset to current source content and,
      files deleted from clone are added back from source.

Type Y (or y) to proceed. Any other key to exit: 

在这个例子中,已经选择了一个先前的克隆进行再次克隆。克隆上的可用空间是一个无关紧要的问题,因为我们已经知道有足够的空间可用。
如果您有多个Ubuntu安装,请确保您选择了正确的分区来克隆当前引导的Ubuntu,挂载为/(根目录)。
这是您最后一次中止的机会,按下除yY之外的任意键即可。

输出列表

当你运行脚本时,你将得到以下输出(不包括上面已列出的输出):

=====================================================================
Using rsync to clone / to /dev/nvme0n1p8 mounted as /mnt/clone16.04
          6.11G  38%   86.46MB/s    0:01:07 (xfr#139123, to-chk=0/647700)   

Number of files: 647,700 (reg: 470,100, dir: 104,694, link: 72,903, special: 3)
Number of created files: 127,824 (reg: 72,472, dir: 15,825, link: 39,526, special: 1)
Number of deleted files: 73,318 (reg: 59,766, dir: 9,701, link: 3,847, special: 4)
Number of regular files transferred: 139,123
Total file size: 15.92G bytes
Total transferred file size: 6.11G bytes
Literal data: 6.11G bytes
Matched data: 0 bytes
File list size: 8.50M
File list generation time: 0.001 seconds
File list transfer time: 0.000 seconds
Total bytes sent: 6.14G
Total bytes received: 7.82M

sent 6.14G bytes  received 7.82M bytes  89.74M bytes/sec
total size is 15.92G  speedup is 2.59

Time to clone files: 68 Seconds

=====================================================================
Making changes in: /mnt/clone16.04/etc/update-manager/release-upgrades
     from Prompt=: never
       to Prompt=: lts
Allows running 'do-release-upgrade -d' when rebooting clone target
Consider 'do-release-upgrade -d -f DistUpgradeViewNonInteractive' This
allows you to go to bed or go to lunch whilst upgrade runs.

* * *  When you Upgrade, TURN OFF screen locking for inactivity. * * *

=====================================================================
Making changes in: /mnt/clone16.04/etc/fstab
        from UUID: f3f8e7bc-b337-4194-88b8-3a513f6be55b
          to UUID: 113f9955-a064-4ce2-9cae-74f2a9518550

=====================================================================
Making changes in: /mnt/clone16.04/boot/grub/grub.cfg
        from UUID: f3f8e7bc-b337-4194-88b8-3a513f6be55b
          to UUID: 113f9955-a064-4ce2-9cae-74f2a9518550
Also change 'quiet splash' to 'nosplash' for environmental awareness
Suggest first time booting clone you make wallpaper unique

=====================================================================
Calling 'update-grub' to create new boot menu
Generating grub configuration file ...
Found background: /home/rick/Pictures/1600x900/21.jpg
Found background image: /home/rick/Pictures/1600x900/21.jpg
Found linux image: /boot/vmlinuz-4.14.34-041434-generic
Found initrd image: /boot/initrd.img-4.14.34-041434-generic
Found linux image: /boot/vmlinuz-4.14.31-041431-generic
Found initrd image: /boot/initrd.img-4.14.31-041431-generic
Found linux image: /boot/vmlinuz-4.14.30-041430-generic
Found initrd image: /boot/initrd.img-4.14.30-041430-generic
Found linux image: /boot/vmlinuz-4.14.27-041427-generic
Found initrd image: /boot/initrd.img-4.14.27-041427-generic
Found linux image: /boot/vmlinuz-4.14.15-041415-generic
Found initrd image: /boot/initrd.img-4.14.15-041415-generic
Found linux image: /boot/vmlinuz-4.14.10-041410-generic
Found initrd image: /boot/initrd.img-4.14.10-041410-generic
Found linux image: /boot/vmlinuz-4.14.4-041404-generic
Found initrd image: /boot/initrd.img-4.14.4-041404-generic
Found linux image: /boot/vmlinuz-4.14.2-041402-generic
Found initrd image: /boot/initrd.img-4.14.2-041402-generic
Found linux image: /boot/vmlinuz-4.13.9-041309-generic
Found initrd image: /boot/initrd.img-4.13.9-041309-generic
Found linux image: /boot/vmlinuz-4.10.0-42-generic
Found initrd image: /boot/initrd.img-4.10.0-42-generic
Found linux image: /boot/vmlinuz-4.9.77-040977-generic
Found initrd image: /boot/initrd.img-4.9.77-040977-generic
Found linux image: /boot/vmlinuz-4.4.0-104-generic
Found initrd image: /boot/initrd.img-4.4.0-104-generic
Found linux image: /boot/vmlinuz-3.16.53-031653-generic
Found initrd image: /boot/initrd.img-3.16.53-031653-generic
Found Windows Boot Manager on /dev/nvme0n1p2@/EFI/Microsoft/Boot/bootmgfw.efi
Found Ubuntu 16.04.3 LTS (16.04) on /dev/nvme0n1p8
Found Windows Boot Manager on /dev/sda1@/efi/Microsoft/Boot/bootmgfw.efi
Adding boot menu entry for EFI firmware configuration
done

=====================================================================
Unmounting /dev/nvme0n1p8 as /mnt/clone16.04

rsync新克隆状态显示

当首次克隆时,rsync将会显示从0到100%的所有已创建文件的更新。由于克隆为空,不会删除或更改任何文件:

clone-ubuntu.sh empty clone.gif

rsync重新克隆时的状态显示

rsync重新克隆时,它永远不会达到100%,因为未更改的文件不会被复制。在更新进度中,rsync会出现延迟,因为它会扫描下一个要复制的文件,并删除在克隆中创建但原始文件中从未存在的新文件:

clone-ubuntu-rsync.gif


Bash脚本 - clone-ubuntu.sh
#!/bin/bash

# NAME: clone-ubuntu.sh
# PATH: /usr/local/bin
# DESC: Written for AU Q&A: https://askubuntu.com/questions/1028604/bash-seemless-safe-script-to-upgrade-16-04-to-18-04/1028605#1028605
# DATE: Apr 27, 2018. Modified May 6, 2018.

# UPDT: May 02 2018 - Display selected parition and get confirmation.
#       May 06 2018 - Revise `do-release-upgrade -d` instructions.
#                     Correct listing of files in empty target partition.
#       Aug 09 2018 - Add --inplace parameter to `rsync`
#                     Comment out disabling `/etc/cron.d` on clone target.
#                     Users may uncomment and/or revise to their needs.

# $TERM variable may be missing when called via desktop shortcut
CurrentTERM=$(env | grep TERM)
if [[ $CurrentTERM == "" ]] ; then
    notify-send --urgency=critical \ 
                "$0 cannot be run from GUI without TERM environment variable."
    exit 1
fi

# Must run as root
if [[ $(id -u) -ne 0 ]] ; then echo "Usage: sudo $0" ; exit 1 ; fi

#
# Create unqique temporary file names
#

tmpPart=$(mktemp /tmp/clone-ubuntu.XXXXX)   # Partitions list
tmpMenu=$(mktemp /tmp/clone-ubuntu.XXXXX)   # Menu list
tmpInf1=$(mktemp /tmp/clone-ubuntu.XXXXX)   # Soucre (Booted) Ubuntu Info
tmpInf2=$(mktemp /tmp/clone-ubuntu.XXXXX)   # Target (Cloned) Ubuntu Info
tmpInf3=$(mktemp /tmp/clone-ubuntu.XXXXX)   # Work file used by DistInfo ()

#
# Function Cleanup () Removes temporary files
#

CleanUp () {
    [[ -f "$tmpPart" ]] && rm -f "$tmpPart" # If we created temp files
    [[ -f "$tmpMenu" ]] && rm -f "$tmpMenu" #  at various program stages
    [[ -f "$tmpInf1" ]] && rm -f "$tmpInf1" #  then remove them before
    [[ -f "$tmpInf2" ]] && rm -f "$tmpInf2" #  exiting.
    [[ -f "$tmpInf3" ]] && rm -f "$tmpInf3"

    if  [[  -d "$TargetMnt" ]]; then        # Did we create a clone mount?
        umount "$TargetMnt" -l              # Unmount the clone
        rm  -d "$TargetMnt"                 # Remove clone directory
    fi
}

#
# Function GetUUID () gets UUIDs of source and clone target partitions in menu.
#

GetUUID () {

    SrchLine="$1"                           # menu line passed to function
    UUID_col=0                              # start column of UUID in line
    lsblk -o NAME,UUID > "$tmpPart"         # Get list of UUID's

    while read -r UUID_Line; do             # Read through UUID list

        # Establish UUID position on line
        if [[ $UUID_col == 0 ]] ; then      # First time will be heading
            UUID_col="${UUID_Line%%UUID*}"  # Establish column number
            UUID_col="${#UUID_col}"         #  where UUID appears on line
            NameLen=$(( UUID_col - 1 ))     # Max length of partition name
            continue                        # Skip to read next line
        fi

        # Check if Passed line name (/dev/sda1, /nvme01np8, etc.) matches.
        if [[ "${UUID_Line:0:$NameLen}" == "${SrchLine:0:$NameLen}" ]] ; then
            FoundUUID="${UUID_Line:UUID_col:999}"
            break                           # exit function
        fi

    done < "$tmpPart"                       # Read next line & loop back
}


#
# Function DistInfo () builds information about source & target partitions
#

DistInfo () {

    Mount="$1"                              # Mount name is '/' or $TargetMnt
    FileName="$2"                           # "$tmpInf1" or "$tmpInf2" work file
    cat "$Mount"/etc/lsb-release >> "$FileName"
    sed -i 's/DISTRIB_//g' "$FileName"      # Remove DISTRIB_ prefix.
    sed -i 's/=/:=/g' "$FileName"           # Change "=" to ":="
    sed -i 's/"//g' "$FileName"             # Remove " around "Ubuntu 16.04...".

    # Align columns from "Xxxx:=Yyyy" to "Xxxx:      Yyyy"
    cat "$FileName" | column -t -s '=' > "$tmpInf3"
    cat "$tmpInf3" > "$FileName"
}


#
# Mainline
#

lsblk -o NAME,FSTYPE,LABEL,SIZE,MOUNTPOINT > "$tmpMenu"

i=0
SPACES='                                                                     '
DoHeading=true
AllPartsArr=()      # All partitions.

# Build whiptail menu tags ($i) and text ($Line) into array

while read -r Line; do
    if [[ $DoHeading == true ]] ; then
        DoHeading=false                     # First line is the heading.
        MenuText="$Line"                    # Heading for whiptail.
        FSTYPE_col="${Line%%FSTYPE*}"           
        FSTYPE_col="${#FSTYPE_col}"         # Required to ensure `ext4`.
        MOUNTPOINT_col="${Line%%MOUNTPOINT*}"
        MOUNTPOINT_col="${#MOUNTPOINT_col}" # Required to ensure not mounted.
        continue
    fi

    Line="$Line$SPACES"                     # Pad extra white space.
    Line=${Line:0:74}                       # Truncate to 74 chars for menu.

    if [[ "${Line:MOUNTPOINT_col:4}" == "/   " ]] ; then
        GetUUID "$Line"
        SourceUUID=$FoundUUID
        # Build "/dev/Xxxxx" FS name from "├─Xxxxx" lsblk line
        SourceDev="${Line%% *}"
        SourceDev=/dev/"${SourceDev:2:999}"
    fi

    AllPartsArr+=($i "$Line")               # Menu array entry = Tag# + Text.
    (( i++ ))

done < "$tmpMenu"                           # Read next "lsblk" line.

#
# Display whiptail menu in while loop until no errors, or escape,
# or valid partion selection .
#

DefaultItem=0

while true ; do

    # Call whiptail in loop to paint menu and get user selection
    Choice=$(whiptail \
        --title "Use arrow, page, home & end keys. Tab toggle option" \
        --backtitle "Clone 16.04 for upgrade.  ONLY CLONES / PARTITION" \
        --ok-button "Select unmounted partition" \
        --cancel-button "Exit" \
        --notags \
        --default-item "$DefaultItem" \
        --menu "$MenuText" 24 80 16 \
        "${AllPartsArr[@]}" \
        2>&1 >/dev/tty)

    clear                                   # Clear screen.
    if [[ $Choice == "" ]]; then            # Escape or dialog "Exit".
        CleanUp
        exit 0;
     fi

    DefaultItem=$Choice                     # whiptail start option.
    ArrNdx=$(( $Choice * 2 + 1))            # Calculate array offset.
    Line="${AllPartsArr[$ArrNdx]}"          # Array entry into $Line.

    # Validation - Don't wipe out Windows or Ubuntu 16.04:
    # - Partition must be ext4 and cannot be mounted.

    if [[ "${Line:FSTYPE_col:4}" != "ext4" ]] ; then
        echo "Only 'ext4' partitions can be clone targets."
        read -p "Press <Enter> to continue"
        continue
    fi

    if [[ "${Line:MOUNTPOINT_col:4}" != "    " ]] ; then
        echo "A Mounted partition cannot be a clone target."
        read -p "Press <Enter> to continue"
        continue
    fi

    GetUUID "$Line"                         # Get UUID of target partition.
    TargetUUID=$FoundUUID

    # Build "/dev/Xxxxx" FS name from "├─Xxxxx" menu line
    TargetDev="${Line%% *}"
    TargetDev=/dev/"${TargetDev:2:999}"

    break                                   # Validated: Break menu loop.

done                                        # Loop while errors.

#
# Mount Clone Target partition
#

Release=$(lsb_release -rs)                  # Source version ie: '16.04'
TargetMnt="/mnt/clone$Release"

echo ""
echo "====================================================================="
echo "Mounting clone partition $TargetDev as $TargetMnt"
mkdir -p "$TargetMnt"                       # '-p' directory may already exist
mount -t auto -v $TargetDev "$TargetMnt" > /dev/null

# Confirm partition is empty. If not empty confirm it's Ubuntu. If not exit.
# If Ubuntu display prompt with the version it contains and get confirmation.

echo ""
echo "====================================================================="
echo "PLEASE: Carefully confirm Source (Live) and Target (Clone) partitions"

# Build source information (our current boot partition)
echo "SOURCE (BOOT /)=$SourceDev"  > "$tmpInf1"
DistInfo "/" "$tmpInf1"                     # /etc/lsb_release information
df -h --output=size,used,avail,pcent "$SourceDev" >> "$tmpInf1"

# Build target information (the partition selected for cloning to)
LineCnt=$(ls "$TargetMnt" | wc -l)
if (( LineCnt > 1 )) ; then 
    # More than /Lost+Found exist so it's not an empty partition.
    if [[ -f "$TargetMnt"/etc/lsb-release ]] ; then
        echo "TARGET (CLONE)=$TargetDev" > "$tmpInf2"
        DistInfo "$TargetMnt" "$tmpInf2"    # /etc/lsb_release information
    else
        # TO-DO: might be cloning /boot or /home on separate partitions.
        #        the source partition is still `/` so can display message.
        echo "Selected partition has data which is not Ubuntu OS. Aborting."
        CleanUp                             # Remove temporary files
        exit 1
    fi
else
    echo "Target (Clone) partition appears empty" > "$tmpInf2"
    echo "/Lost+Found normal in empty partition" >> "$tmpInf2"
    echo "Head of '/Clone/' files & directories:" >> "$tmpInf2"
    ls "$TargetMnt" | head -n2 >> "$tmpInf2"
fi

# Target device free bytes
df -h --output=size,used,avail,pcent "$TargetDev" >> "$tmpInf2"

# Display source and target partitions side-by-side using bold text.
echo $(tput bold)       # Set to bold text
paste -d '|' "$tmpInf1" "$tmpInf2" | column -t -s '|'
echo $(tput sgr0)       # Reset to normal text

echo "NOTE: If you are recloning, new files in clone will be deleted,"
echo "      modified files are reset to current source content and,"
echo "      files deleted from clone are added back from source."
echo ""

read -p "Type Y (or y) to proceed. Any other key to exit: " -n 1 -r
echo    # (optional) move to a new line
if [[ ! $REPLY =~ ^[Yy]$ ]] ; then
    CleanUp             # Remove temporary files
    exit 0
fi

# Copy non-virtual directories to clone. Credit to TikTak's Ask Ubuntu answer:
# https://askubuntu.com/questions/319805/is-it-safe-to-clone-the-current-used-disk?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

SECONDS=0
echo ""
echo "====================================================================="
echo "Using rsync to clone / to $TargetDev mounted as $TargetMnt"
rsync -haxAX --stats --delete --info=progress2 --info=name0 --inplace  \
      /* "$TargetMnt"                                                   \
      --exclude={/dev/*,/proc/*,/sys/*,/tmp/*,/run/*,/mnt/*,/media/*,/lost+found}
# For 16GB on Samsung Pro 960: First time 98 seconds, second time 27 seconds.
rsyncTime=$SECONDS  
echo ""
echo "Time to clone files: $rsyncTime Seconds"

# Change /etc/update-manager/release-upgrades prompt from never to LTS
echo ""
echo "====================================================================="
echo "Making changes in: $TargetMnt/etc/update-manager/release-upgrades"
echo "     from Prompt=: never"
echo "       to Prompt=: lts"
echo "Allows running 'do-release-upgrade -d' when rebooting clone target"
echo "Consider 'do-release-upgrade -d -f DistUpgradeViewNonInteractive' This"
echo "allows you to go to bed or go to lunch whilst upgrade runs."
echo ""
echo "* * *  When you Upgrade, TURN OFF screen locking for inactivity. * * *"
echo ""
sed -i 's/Prompt=never/Prompt=lts/' "$TargetMnt"/etc/update-manager/release-upgrades

## This section commented out to prevent surprises. You may uncomment.
## You may want to revise to include `cron.daily`, `cron.hourly`, etc.
# Move `/etc/cron.d` reboot jobs to `/etc/cron.d/hold` to prevent running
# scripts such as daily backup or Ubuntu 16.04 specific problem fixes.
#echo ""
#echo "====================================================================="
#echo "Moving '$TargetMnt/etc/cron.d' to '.../hold' to prevent running."
#echo "After booting clone, move back individual files you want to run"
#if [[ ! -d "$TargetMnt"/etc/cron.d/hold ]]; then
#    mkdir "$TargetMnt"/etc/cron.d/hold
#fi
#cp -p  "$TargetMnt"/etc/cron.d/* "$TargetMnt"/etc/cron.d/hold/
#rm -fv "$TargetMnt"/etc/cron.d/*

# Update /etc/fstab on clone partition with clone's UUID
echo ""
echo "====================================================================="
echo "Making changes in: $TargetMnt/etc/fstab"
echo "        from UUID: $SourceUUID"
echo "          to UUID: $TargetUUID"
sed -i "s/$SourceUUID/$TargetUUID/g" "$TargetMnt"/etc/fstab

# Update /boot/grub/grub.cfg on clone partition with clone's UUID
echo ""
echo "====================================================================="
echo "Making changes in: $TargetMnt/boot/grub/grub.cfg"
echo "        from UUID: $SourceUUID"
echo "          to UUID: $TargetUUID"
echo "Also change 'quiet splash' to 'nosplash' for environmental awareness"
echo "Suggest first time booting clone you make wallpaper unique"
sed -i "s/$SourceUUID/$TargetUUID/g" "$TargetMnt"/boot/grub/grub.cfg
sed -i "s/quiet splash/nosplash/g" "$TargetMnt"/boot/grub/grub.cfg

# Update grub boot menu
echo ""
echo "====================================================================="
echo "Calling 'update-grub' to create new boot menu"
update-grub

# Unmount and exit

echo ""
echo "====================================================================="
echo "Unmounting $TargetDev as $TargetMnt"

CleanUp             # Remove temporary files

exit 0

将上面的bash代码复制并粘贴到一个名为/usr/local/bin/clone-ubuntu.sh的新文件中。然后使用以下命令使新文件可执行:
sudo chmod a+x /usr/local/bin/clone-ubuntu.sh

调用脚本使用:
sudo clone-ubuntu.sh

如何将16.04 LTS克隆升级到Ubuntu 18.04 LTS

这是一个可能会吸引很多人的“额外”部分。

重新启动您的机器。 grub 菜单中将包含指向克隆分区的新菜单选项。您还可以从克隆的高级选项菜单中选择特定的内核版本。

将克隆的16.04 LTS转换为18.04 LTS的一种方法是运行:

sudo do-release-upgrade

请注意,在2018年7月26日之前,需要使用-d标志,但现在不再需要。 仔细阅读18.04升级确认事项
在继续之前,请确保关闭非活动屏幕锁定。如果您的计算机因键盘不活动而进入锁屏状态,升级过程可能会崩溃。

18.04升级流程摘要

此部分将根据不同用户安装的不同应用程序进行具体说明。以下是我根据笔记和记忆制作的简要摘要:
确认继续进行:输入ENTER 将删除软件包:Y 替换longind.conf文件:Y 配置文件'/etc/sane.d/dll.conf',默认为N,选择Y '/etc/NetworkManager/conf.d/default-wifi-powersave-on.conf'文件选择默认值N 配置文件'/etc/pulse/default.pa',默认为N,选择Y 配置文件'/etc/grub.d/30_os-prober',默认为N,选择N 全屏grub菜单配置出现。选择选项:保留当前安装的本地版本 配置文件'/etc/cron.d/anacron',默认为N,选择Y以查看内容 多次出现错误消息:/sbin/ldconfig.real: 警告:忽略无法打开的配置文件:/etc/ld.so.conf.d/x86_64-linux-gnu_EGL.conf: 没有此文件或目录 非标准:配置文件'/etc/vnstat.conf'(显示差异1.13与1.18),选择Y 将删除220个软件包。(可能需要几个小时)输入Y 完成升级需要重新启动。选择Y
注意第10步,大多数人都看不到。我在我的Ubuntu 16.04上安装了一个旧的nVidia驱动程序,但从未完全删除。这是因为您可能有类似的旧软件包没有完全删除。

Grub将引导菜单更改为UEFI下的克隆

与18.04升级不同,我发现18.04.1升级将Grub UEFI配置更改为使用克隆的grub菜单,而不是原始的grub菜单,如此答案所述:Dual boot and the files /boot/grub/grub.cfg -- which one is used?
$ sudo cat /boot/efi/EFI/ubuntu/grub.cfg
search.fs_uuid b40b3925-70ef-447f-923e-1b05467c00e7 root 
set prefix=($root)'/boot/grub'
configfile $prefix/grub.cfg

$ sudo grub-install
Installing for x86_64-efi platform.
Installation finished. No error reported.

在启动原始分区后运行sudo update-grub并不足以更改由grub加载的grub.cfg。您需要使用sudo grub-install强制grub使用原始分区的配置。
原始分区和克隆分区都可以使用update-grub来维护自己的/boot/grub/grub.cfg文件,但只能在启动时使用一个。
当然,如果您希望grub使用Clone的grub菜单,则不要在原始分区上执行上述步骤。

编辑历史

编辑于2018年5月6日 - 修正了空克隆(目标)分区的信息显示。

编辑于2018年8月26日 - 使用--inplace选项和rsync一起,以便在复制过程中不会重复复制大文件(如2 GB大小的垃圾文件)到克隆中。这可能导致"磁盘空间不足"错误。注释掉/etc/cron.d覆盖,因为用户可能想要保留或者选择一个不同的目录。更新指南,使用不带-d标志的do-release-upgrade,因为Ubuntu 18.04.1 LTS已经发布。


1+1。感谢这个有用的工具 :-) - sudodus
1@sudodus希望人们在进行18.04升级之前使用这个工具。至少他们可以将其用作教程,并手动重复使用Live USB启动来执行步骤。很可悲的是,有很多人在全新的18.04上遇到了许多错误,因为他们在没有进行测试的情况下进行了升级,并且通过清除他们之前的16.04、17.04或17.10安装来承诺。可悲的是,我在过去几十年中已经见过类似的事情发生很多次。感谢您的点赞!它有助于加强对clone-ubuntu.sh等努力的支持。但无论如何,我自己已经使用了这个工具4次! - WinEunuuchs2Unix
1我还没有使用过你的脚本,但我了解它非常有用,我打算使用它。-- 我曾经成功地从8.04升级到10.04再到12.04,长时间以来一直在使用。但当我尝试通过14.04升级到16.04时失败了。幸好我有很好的备份,所以我进行了一次全新安装的16.04,并将我想要保留的内容复制过去,并检查了调整、脚本、别名和已安装的程序。-- 顺便说一下,我正在开发一个用于创建和升级持久化的可启动驱动器 'home-rw' 的脚本。欢迎尝试一下 :-) - sudodus
1您的链接中有一个小错误:我在8.04 LTS上测试了它们都 应该在末尾改为 18.04 LTS。对于许多没有足够硬盘空间来克隆Ubuntu 16.04的人来说,您的工具是他们的首选。它比在硬盘上创建新分区更容易(虽然速度较慢)。 - WinEunuuchs2Unix
我修正了拼写错误,谢谢 :-) 你对克隆(或复制内容)到硬盘的观点是正确的。但对于那些想要将持久化的活动系统随身携带的人来说,使用我的工具确实很方便。 - sudodus
@sudodus 我无法为你提供的实时持久引导USB的能力作出足够的保证。它绝对是太棒了!我还鼓励你在这个帖子上写一个答案。你会得到我的自动点赞!另一个克隆16.04的优点是安装nVidia驱动程序,有时会搞乱系统。在真正的系统之前,先在克隆上试一下吧。 - WinEunuuchs2Unix
在我Linux Mint 19.1的系统上完美运行...我会再试一次,以测试启动(并最终切换)到NVMe固态硬盘。将grub移动/重新安装/其他操作到新驱动器应该相当简单。 - dentex
我在一个USB上安装了Ubuntu,并且想要将其克隆到另一个USB上。我使用了这个脚本,但现在我不知道如何使那个USB可启动(复制grub命令)不起作用。 - Naveed Abbas
@NaveedAbbas 这个脚本不适用于克隆MBR、GPT、Grub或Windows。它只能克隆Ubuntu。要克隆整个驱动器(USB),请参考:https://www.ubuntupit.com/top-15-best-disk-cloning-software-for-linux/ - WinEunuuchs2Unix
我认为你应该把这个放在GitHub上,这样可以更容易地进行维护。 - AmanicA
@AmanicA 别人已经做过那个并进行了改进:https://github.com/thiggy01/clone-ubuntu - WinEunuuchs2Unix
我可以确认这个在Ubuntu 20.04上也能工作。然而,当目标分区无法正确挂载时,脚本可能会报错,因为我没有对目标分区进行mkfs.ext4(我的错误),而脚本却愉快地将/复制到/mnt/...子目录中,即使那里没有任何东西被挂载。 - Jurriaan
我使用这个脚本将我的硬盘数据转移到了固态硬盘。在启动时,当我从grub菜单中选择SSD上的ubuntu时,它仍然会启动到旧的硬盘上的ubuntu系统。请帮助我。 - Yogi Katba
不确定我做错了什么,但是在最后我得到了"umount: /mnt/clone20.04: not mounted."的错误提示。 - Emanuel Moecklin
在运行脚本之前,请确保您创建的分区可以手动挂载和卸载。可以将一两个文件复制到其中,并确保它们是正确的。请参考:https://askubuntu.com/questions/1029040/how-to-manually-mount-a-partition - WinEunuuchs2Unix
我也收到了一个错误信息,新的分区可以手动挂载,并且文件可以写入其中。脚本退出并返回以下内容: '正在卸载 /dev/me0n1 作为 /mnt/clone20.04 umount: /mnt/clone20.04: 未挂载。 rm: 无法删除 '/mnt/clone20.04': 目录非空' 并且没有文件被复制到目标设备中。 - kurja
@kurja 你的/dev/me0n1是什么类型的驱动器? - WinEunuuchs2Unix
这是一个安装在PCIe扩展槽/适配器中的M.2 NVMe。就我所知,它的工作方式与其他驱动器相同。关于这些是否存在已知问题,我需要在晚上回家后再仔细研究一下脚本运行时的具体情况。 - kurja
df /mnt/clone20.04 告诉我它存储在 sdc5 上(也就是我的 / )。/dev/me0n1 更有趣 - 它并不存在,实际上驱动器是 nvme0n1!在 whiptail 菜单中选择目标分区时,它会正确显示,但之后出现问题。这是运行脚本的完整输出:https://pastebin.com/QdNtEqu1 - kurja
@kurja 你不能选择nvme0n1作为克隆目标,你必须选择其中一个分区。例如,选择第三个分区nvme0n1p3。在克隆到分区之前,你必须先创建该分区。你是否创建了克隆分区? - WinEunuuchs2Unix
1@WinEunuuchs2Unix,所以你说是一个rtfm错误?:)我似乎把自己搞糊涂了,先在设备上创建了一个文件系统,而不是先分区。脚本现在可以无错误运行了,谢谢。 - kurja

从之前的版本升级到18.04 LTS存在的问题

从之前的版本升级到18.04 LTS并不是一件简单的事情。我不知道是否比以往的升级过程中出现了更多的问题,但是那些现在进行升级的人们为自己承担了风险。另一方面,他们发现了一些错误,如果这些错误被报告了,将有助于改进升级工具并调试Ubuntu 18.04 LTS系统本身。

这意味着那些足够耐心等待正式发布第一个点版本(18.04.1 LTS)的人们将会得到更顺利的升级体验。

在进行完整升级之前进行测试...

@WinEunuuchs2Unix在这里描述的方法可以让您使用真实系统的副本进行测试,以确定将当前[或多或少修改过的]操作系统与计算机硬件升级到18.04 LTS是否可行。

这可以避免操作系统损坏导致的多种灾难。

我还没有使用@WinEunuuchs2Unix的脚本,但我了解它非常有用,我打算使用它。我曾经成功地从8.04升级到10.04再到12.04,我长时间使用了这个版本。但是当我尝试通过14.04升级到16.04时失败了,找不到错误所在。
...如果出现问题,重新安装
我有很好的备份,所以我进行了一次全新安装16.04,然后复制了我想要保留的内容,并检查了调整、脚本、别名和已安装的程序。如果我使用了@WinEunuuchs2Unix的方法,我会早点发现问题,直接进行全新安装。
升级持久化的Live系统
持久化的Live系统用于获取非常便携的Ubuntu系统,有时用于测试,有时长时间使用。
众所周知,你不应该像更新和升级已安装的系统那样更新和升级这样的系统,因为它迟早会损坏。此外,你被困在内核和内核驱动程序上,它们与iso文件一起启动,在覆盖系统启动之前启动。

但通常可以保留/home目录,就像在独立的“home”分区上进行全新安装时一样。如果创建一个home-rw分区,持久化的实时系统将会在启动时自动找到并使用它。

我正在开发和测试一个名为mk-persistent-live_with_home-rw的shell脚本,它可以创建一个带有home-rw分区的持久化实时系统,并且可以之后升级它。

  • 使用更新的iso文件替换旧的iso文件。每当发布新的iso文件时,至少应该进行升级,但也可以每月升级一次LTS系统,并使用testing tracker中的当前每日iso文件。

  • 修改grub以适应新的iso文件。

  • 清除(重新格式化)存储操作系统修改的casper-rw文件(因此您必须重新安装添加到系统中的程序包),

  • 保留带有个人文件、设置和调整的home-rw分区。

  • 更多详细信息请参见this link

额外链接

想要测试Ubuntu最新版本的人可以在以下链接中找到一些通用提示:

如何参与Ubuntu的测试和开发


1额外的链接是一个不错的点子。越多人报告问题,就能解决更多问题,让其他人受益。 - WinEunuuchs2Unix
1对于习惯谨慎的LTS用户来说,等待第一个点版本18.04.1是一个非常好的选择。对于较大的组织来说,他们可能仍然希望将16.04克隆到测试分区,并将其升级到18.04以进行员工培训。用户将能够访问他们习惯使用的数据。当然,在7月26日的第一个点版本发布之前,IT人员也会从对克隆数据进行广泛测试中受益。 - WinEunuuchs2Unix