OpenCV是一个基于BSD许可发行的跨平台计算机视觉和机器学习软件库，可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效，同时提供了Python、Ruby、MATLAB等语言的接口，实现了图像处理和计算机视觉方面的很多通用算法。为了方便在树莓派上使用，我制作了一个OpenCV-4.5.0直刷镜像。镜像说明这个镜像是基于树莓派官方raspios-buster-arm64桌面版镜像制作，内核版本为5.4.72，OpenCV版本为4.5.0，默认开启ssh和vnc，更换清华源，4B支持USB启动，第一次开机自动扩容。兼容3B、3B+、4B。支持开机前配置wifi，方法和官方系统一样，在boot分区创建wpa_supplicant.conf文件。根据需要配置一个或多个wifi连接信息，将ssid和password替换为真实值即可。示例：ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 country=CN network={ ssid="无线ssid" psk="无线密码" key_mgmt=WPA-PSK priority=1 } 默认用户/密码：pi/raspberry，root用户没有启用，如果需要请自行开启。默认swap大小为100M，如需修改，请编辑/etc/dphys-swapfile文件，修改CONF_SWAPSIZE=100，单位为MB，如果需要设置1G，则配置为CONF_SWAPSIZE=1024，保存文件执行sudo systemctl restart dphys-swapfile.service重启服务即可。其他配置项可以通过sudo raspi-config进行设置，跟官方系统相同。OpenCV信息：opencv-4.5.0源码目录：/home/pi/opencv/opencv-4.5.0opencv_contrib目录：/home/pi/opencv/opencv_contrib-4.5.0构建目录：/home/pi/opencv/build安装前缀：/usr/local想自己折腾的同学也可以自己编译，在树莓派4B4G上编译大约需要2个小时，不想折腾的可以直刷这个镜像。以下是几个python3的Demo在4B4G运行效果:下载地址下载地址：https://pan.baidu.com/s/1Et9M-iltupnsPgtzTzzqgw ，提取码：v65p本文为原创文章，版权归 Kevin's Blog 所有，转载请联系博主获得授权。
玩树莓派的小伙伴可能遇到这样的烦恼，手里只有一张卡或者一块ssd，但是又想体验不同的系统，无奈只能重复的刷系统，可以说相当麻烦了，今天就说一说树莓派如何安装双系统。数据无价，本教程的操作有一定的风险，开始前请备份重要数据！！！前言树莓派官方提供的NOOBS是可以实现多系统安装的，但是也存在一定的弊端，NOOBS本省会占用一定的空间造成空间浪费，系统都是从国外服务器在线下载，速度可想而知，而且需要显示器(从2015年开始玩pi的我到现在也没有显示器，穷啊)，最主要的还是不符合玩家折腾的精神，所以我们不使用NOOBS，我们自己实现一个不需要显示器的双系统。材料准备树莓派4bSD卡一张(16G或以上)，或硬盘一块母-母杜邦线一条Linux操作系统(推荐Ubuntu)，或者直接使用树莓派本身SD卡或者USB都可以做双系统，我这里使用一张64G卡，操作系统我直接使用树莓派，如果你只有一张卡，那只能使用电脑或者虚拟机了。安装我选择的两个系统是官方系统和基地2.0，可以根据自己的需求更换。0x00.准备工作打开终端#切换到root sudo -i #更新系统软件 apt update apt upgrade apt install dosfstools kpartx rsync #创建工作目录 mkdir dualboot cd dualboot #创建挂载目录 mkdir boot root osimg #上传两个要安装的系统镜像到这个目录 #2020-08-20-raspios-buster-armhf.img #2020-06-22-OPENFANS-Debian-Buster-Desktop-Aarch64-ext4-v2020-2.0-U4-Release.img0x01.分区插卡，对介质进行分区和格式化查看设备lsblk我这里设备名称是sda，根据自己情况替换#分区 cfdisk /dev/sda删除原有所有分区创建三个分区，一个boot分区(fat32)512M，两个系统分区(ext4)创建boot分区创建第一个系统分区，我这里设置30G，大家根据自己需求设置第二个系统分区创建同上将改变写入磁盘按q退出cfdisk，检查磁盘分区lsblk格式化，注意替换自己的设备名称：#格式化boot分区 mkfs.fat -F 32 -n "boot" /dev/sda1 #格式化第一个系统分区，设置label mkfs.ext4 -L rootfs1 /dev/sda2 #格式化第二个系统分区，设置label mkfs.ext4 -L rootfs2 /dev/sda3挂载boot分区mount /dev/sda1 boot/ #创建两个系统的boot目录 mkdir boot/{os1,os2}0x02.安装OS1OS1安装官方系统#挂载OS1的分区 mount /dev/sda2 root/ #挂载系统镜像 losetup -f --show 2020-08-20-raspios-buster-armhf.img我这里是/dev/loop0，你的结果可能跟我不一样，在下面的命令中请将这个值替换为自己的结果。#挂载镜像文件两个分区设备 kpartx -va /dev/loop0 mount /dev/mapper/loop0p2 osimg/ mount /dev/mapper/loop0p1 osimg/boot/ #拷贝OS1的boot目录 cp -a osimg/boot/* boot/os1/ umount osimg/boot/ #同步rootfs rsync -axv osimg/ root/ mkdir root/bootpar sed -i "s/\(PARTUUID=\)[[:xdigit:]-]\+\([[:blank:]]*\)\/boot/\1$(blkid -o value -s PARTUUID /dev/sda1)\2\/bootpar/" root/etc/fstab sed -i "s/\(PARTUUID=\)[[:xdigit:]-]\+\([[:blank:]]*\/[[:blank:]]\+\)/\1$(blkid -o value -s PARTUUID /dev/sda2)\2/" root/etc/fstab echo -e "/bootpar/os1 /boot none bind 0 0\n" >> root/etc/fstab sed -i "s/\(PARTUUID=\)[[:xdigit:]-]\+/\1$(blkid -o value -s PARTUUID /dev/sda2)/" boot/os1/cmdline.txt #禁止自动扩容 sed -i 's/init=\/usr\/lib\/raspi-config\/init_resize.sh//' boot/os1/cmdline.txt sync && sync umount root/ umount osimg/ kpartx -d /dev/loop0 losetup -d /dev/loop00x03.安装OS2OS2安装基地2.0#挂载OS2的分区 mount /dev/sda3 root/ #挂载系统镜像 losetup -f --show 2020-06-22-OPENFANS-Debian-Buster-Desktop-Aarch64-ext4-v2020-2.0-U4-Release.img我这里是/dev/loop0，你的结果可能跟我不一样，在下面的命令中请将这个值替换为自己的结果。#挂载镜像文件两个分区设备 kpartx -va /dev/loop0 mount /dev/mapper/loop0p2 osimg/ mount /dev/mapper/loop0p1 osimg/boot/ #拷贝OS2的boot目录 cp -a osimg/boot/* boot/os2/ umount osimg/boot/ #同步rootfs rsync -axv osimg/ root/ mkdir root/bootpar sed -i "s/\(PARTUUID=\)[[:xdigit:]-]\+\([[:blank:]]*\)\/boot/\1$(blkid -o value -s PARTUUID /dev/sda1)\2\/bootpar/" root/etc/fstab sed -i "s/\(PARTUUID=\)[[:xdigit:]-]\+\([[:blank:]]*\/[[:blank:]]\+\)/\1$(blkid -o value -s PARTUUID /dev/sda3)\2/" root/etc/fstab echo -e "/bootpar/os2 /boot none bind 0 0\n" >> root/etc/fstab sed -i "s/\(PARTUUID=\)[[:xdigit:]-]\+/\1$(blkid -o value -s PARTUUID /dev/sda3)/" boot/os2/cmdline.txt sync && sync umount root/ umount osimg/ kpartx -d /dev/loop0 losetup -d /dev/loop00x04.处理bootcp boot/os1/fixup* boot/ cp boot/os1/start* boot/ cp boot/os1/config.txt boot/编辑boot/config.txt，在文件最前面加入以下内容：[gpio2=1] os_prefix=os1/ hdmi_force_hotplug=1 hdmi_group=2 hdmi_mode=85 [gpio2=0] os_prefix=os2/ #配置基地2.0需要的参数 arm_64bit=1 arm_control=0x200 kernel=kernel8.img disable_splash=1 dtparam=random=on hdmi_force_hotplug=1 initramfs initrd.img disable_overscan=1 dtparam=audio=on对于不同系统上面的配置会有些许不同，大家灵活处理。0x05.收尾sync && sync umount boot/现在树莓派的双系统安装完成。不短接任何引脚默认启动os1。用母-母杜邦线短接3.3v和gpio2后再上电启动os1。用母-母杜邦线短接GND和gpio2后再上电启动os2。动手能力强的小伙伴可以做个开关控制不同系统启动 ^_^如果觉得短接引脚麻烦，也可以用替换文件的方法切换系统：用boot/os1/config.txt覆盖boot/config.txt，启动os1用boot/os2/config.txt覆盖boot/config.txt，启动os2替换文件的方法可以在win下操作，也可以在linux下操作。测试os1：插上制作好的SD卡，用杜邦线短接3.3V和gpio2：os2：用杜邦线短接GND和gpio2：双系统安装到不同设备也是可以实现的，原理都是一样的。以上就是树莓派双系统的教程，很多地方都是很灵活的，方法不止一种，遇到问题要善于思考，实在思考不明白可以找我一起讨论。本文为原创文章，版权归 Kevin's Blog 所有，转载请联系博主获得授权。
Java是一门面向对象编程语言，不仅吸收了C++语言的各种优点，还摒弃了C++里难以理解的多继承、指针等概念，因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表，极好地实现了面向对象理论，允许程序员以优雅的思维方式进行复杂的编程。今天讲一下树莓派如何配置Oracle JDK8。数据无价，本教程的操作有一定的风险，开始前请备份重要数据！！！jdk8下载地址：https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html下载需要登录，也可以直接使用我下载的8u261#切换到root用户 sudo -i #根据自己系统选择arm32或者arm64 #arm32 wget https://linuxer.top/usr/uploads/2020/07/jdk-8u261-linux-arm32-vfp-hflt.tar.gz tar -zxvf jdk-8u261-linux-arm32-vfp-hflt.tar.gz -C /usr/local/ #arm64 wget https://linuxer.top/usr/uploads/2020/07/jdk-8u261-linux-arm64-vfp-hflt.tar.gz tar -zxvf jdk-8u261-linux-arm64-vfp-hflt.tar.gz -C /usr/local/ #创建软连接，方便升级 ln -sf /usr/local/jdk1.8.0_261/ /usr/local/jdk1.8增加环境变量，编辑文件/etc/profile，在最后增加以下内容并保存：export JAVA_HOME=/usr/local/jdk1.8 export PATH=$JAVA_HOME/bin:$PATH使环境变量生效：source /etc/profile检查版本：java -version本文为原创文章，版权归 Kevin's Blog 所有，转载请联系博主获得授权。
搞开发的同学都应该知道git，可以说git是目前最先进的分布式版本控制系统，没有之一。git的诞生也有着传奇色彩，最初Linux内核的版本控制使用的是闭源的商业软件BitKeeper，后来因为一些事情Linux团队跟他们闹翻了，Linus Torvalds决定开发自己的版本管理系统不再受制于人，10天后git诞生了，没错是10天！数据无价，本教程的操作有一定的风险，开始前请备份重要数据！！！git的优点不再赘述，主要讲一下如何在树莓派上用Gitea部署自己的git代码托管平台。如果是大、中型团队推荐使用GitLab，如果是中、小型团队或者个人使用，那么Gitea非常适合你。Gitea是一个开源社区驱动的Gogs克隆，是一个轻量级的代码托管解决方案，后端采用Go编写，采用MIT许可证。可运行在Windows、macOS、Linux、ARM等平台。相比Gogs来说更新频率更高，推荐使用。推荐使用基地2.0系统进行部署。首先参考https://linuxer.top/archives/raspi-install-mysql57.html这篇文章安装Mysql数据库或者MariaDB，当然也可以不安装，Gitea也支持使用SQLite，推荐使用Mysql或MariaDB。Mysql创建数据库gitea编码使用utf8mb4，创建用户gitea，把数据库gitea的权限赋给用户gitea。配置环境：#更新系统 sudo apt update sudo apt upgrade #安装git #如果想用最新版git可以参考git官网编译安装 sudo apt install git #创建git用户 sudo useradd -m -s /bin//bash git #切换到git su - git #创建工作目录 mkdir gitea cd gitea #到https://github.com/go-gitea/gitea/releases #找最新的arm64发布版本地址 #目前是1.12.1 #下载 wget https://github.com/go-gitea/gitea/releases/download/v1.12.1/gitea-1.12.1-linux-arm64.xz #解压 xz -d gitea-1.12.1-linux-arm64.xz #赋执行权限 chmod u+x gitea-1.12.1-linux-arm64 #创建软连接，方便更新 ln -sf gitea-1.12.1-linux-arm64 gitea #如果需要更新版本的时候，先停掉服务 #下载最新的可执行文件解压 #创建软连接到最新版 #ln -sf gitea-x.xx.x-linux-arm64 gitea #然后启动服务 #启动服务 #sudo systemctl start gitea.service #停止服务 #sudo systemctl stop gitea.service创建systemd服务开一个新终端窗口，用root权限创建文件/etc/systemd/system/gitea.service，内容如下：[Unit] Description=Gitea (Git with a cup of tea) After=syslog.target After=network.target #根据使用的数据库打开下面的注释 #我这里用的mysql Requires=mysql.service #Requires=mariadb.service [Service] #LimitMEMLOCK=infinity #LimitNOFILE=65535 RestartSec=2s Type=simple User=git Group=git WorkingDirectory=/home/git/gitea/ ExecStart=/home/git/gitea/gitea web Restart=always Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/home/git/gitea [Install] WantedBy=multi-user.target使用root权限启动服务：#刷新服务 systemctl daemon-reload #设置开机启动 systemctl enable gitea.service #启动 systemctl start gitea.service这时服务已经启动，访问ip:3000/install进行安装配置，我这里的地址是192.168.1.240:3000/install数据库配置：一般配置，这里的各种路径根据自己需求进行填写，不明白什么意思的就保持默认：可选设置中配置管理员账户，注意，这里不能用admin作为用户名:没有提到的配置大家根据自己需求设置，然后开始安装，安装完成后跳转到首页：部署完成，更多的功能大家自己探索吧~本文为原创文章，版权归 Kevin's Blog 所有，转载请联系博主获得授权。
树莓派启动时会根据核心数量显示不同数量的树莓logo，今天讲一下如何替换这个树莓logo。数据无价，本教程的操作有一定的风险，开始前请备份重要数据！！！这个logo是在内核中的，不能通过替换资源文件的方式更换，只能在内核源码中替换，然后编译内核才能生效。首先clone内核源码：git clone --depth=1 https://github.com/raspberrypi/linux默认图片的位置在drivers/video/logo/logo_linux_clut224.ppmppm也是一种图片格式，大家可以百度一下，这个ppm转为png后就是下图：分辨率为63x80，我们先制作一个相同分辨率的png，logo.png然后安装netpbmapt update apt install netpbm然后开始转换：pngtopnm logo.png | ppmquant -fs 224 | pnmtoplainpnm > logo_linux_clut224.ppm将logo_linux_clut224.ppm覆盖内核原文件，然后编译安装内核。内核编译安装步骤参考https://linuxer.top/archives/build-raspi-osimg.html最后上个效果图：本文为原创文章，版权归 Kevin's Blog 所有，转载请联系博主获得授权。
树莓派从3B开始就是64位cpu，但是官方系统一直都是32位的，直到2020-05-28才发布64位beta版，在此之前我除了使用基地的64位系统之外也自己构建过，这篇文章将详细讲一下如何从零开始构建自己的树莓派64位系统。数据无价，本教程的操作有一定的风险，开始前请备份重要数据！！！树莓派官方系统是基于Debian的，所以我们也选择Debian Buster进行构建。整个构建过程可以在安装Linux系统的PC或服务器上进行，也可以在64位树莓派上进行(推荐使用基地2.0最新的u3)，我使用x64平台的Ubuntu 20.04进行演示，过程中我会说明与使用树莓派不同的地方，没有说明的就是通用的。一、准备镜像我们首先来创建镜像文件，这次我们构建的是lite系统不包含桌面环境，所以我创建一个3G的镜像(其实2G就够)，这里可以根据自己定制的需要改变镜像的大小。为了避免频繁使用sudo，全程使用root用户操作。#切换到root sudo -i #更新系统软件 apt update apt upgrade #安装所需要的软件 apt install kpartx #创建一个工作目录，所有工作都在此目录进行 mkdir debian cd debian #创建镜像文件buster.img dd if=/dev/zero of=buster.img bs=3G count=0 seek=1 #给镜像文件分区 cfdisk buster.img树莓派系统镜像有两个分区，一个boot分区类型为FAT32，一个rootfs根分区类型为ext4，下面开始分区进入cfdisk交互模式后，选择dos类型：然后用左右键选择新建，输入分区大小256M，类型选择主分区：然后用上下键选择刚刚创建的256M分区，左右键选择类型，弹出对话框选择类型c：然后在剩余空间上选择新建，分区大小默认，类型选择主分区：然后有左右按键选写入，提示输入yes：然后按q键或者选择退出。镜像分区完成，现在开始格式化镜像：#挂载镜像文件 losetup -f --show buster.img执行完上面的挂载命令会得到一个输出，表示挂载的loop设备：我这里是/dev/loop10，你的结果可能跟我不一样，在下面的命令中请将这个值替换为自己的结果。#挂载镜像文件两个分区设备 kpartx -va /dev/loop10执行完上面的命令会把两个分区设备映射到/dev/mapper/下，具体设备名称看自己的输出：我的结果表明，镜像第一个分区设备为/dev/mapper/loop10p1，第二个分区设备为/dev/mapper/loop10p2格式化两个分区，注意替换自己的设备名称：#格式化boot分区 mkfs.fat -F 32 -n "boot" /dev/mapper/loop10p1 #格式化rootfs，设置label mkfs.ext4 -L rootfs /dev/mapper/loop10p2创建两个挂载点并挂载两个分区：mkdir boot rootfs #挂载boot mount /dev/mapper/loop10p1 boot/ #挂载rootfs mount /dev/mapper/loop10p2 rootfs/执行lsblk确认一下挂载情况：镜像准备完毕。二、rootfs构建现在开始rootfs的构建#安装所需要的软件 #x64平台 apt install debootstrap qemu-user-static #树莓派 apt install debootstrap #使用debootstrap构建基础系统 #--arch=arm64指定目标架构 #buster表示要构建的发行版 #rootfs/表示构建目录 #https://mirrors.tuna.tsinghua.edu.cn/debian/ 表示使用的源 #x64执行 #--foreign表示异构系统构建 debootstrap --arch=arm64 --no-merged-usr --foreign buster rootfs/ https://mirrors.tuna.tsinghua.edu.cn/debian/ #树莓派执行 debootstrap --arch=arm64 --no-merged-usr buster rootfs/ https://mirrors.tuna.tsinghua.edu.cn/debian/ #下载驱动 wget https://linuxer.top/usr/uploads/2020/06/firmware.tar.xz #解压驱动 tar -Jxvf firmware.tar.xz -C rootfs/lib/ #下载固件 wget -O rpi-firmware.tar.gz https://github.com/Hexxeh/rpi-firmware/tarball/master mkdir rpi-firmware tar -zxvf rpi-firmware.tar.gz -C rpi-firmware --strip-components 1 cp -r rpi-firmware/vc/hardfp/opt/vc rootfs/opt/ cp -r rpi-firmware/vc/sdk/opt/vc rootfs/opt/执行blkid /dev/mapper/loop10*，根据结果编辑rootfs/etc/fstab文件:我的rootfs/etc/fstab文件内容如下，大家根据实际情况修改：proc /proc proc defaults 0 0 PARTUUID=ec5f336e-01 /boot vfat defaults 0 2 PARTUUID=ec5f336e-02 / ext4 defaults,noatime 0 1改为清华源，编辑rootfs/etc/apt/sources.list,修改为以下内容：deb http://mirrors.tuna.tsinghua.edu.cn/debian/ buster main non-free contrib deb http://mirrors.tuna.tsinghua.edu.cn/debian-security buster/updates main deb http://mirrors.tuna.tsinghua.edu.cn/debian/ buster-updates main non-free contrib deb http://mirrors.tuna.tsinghua.edu.cn/debian/ buster-backports main non-free contrib扩容脚本，创建rootfs/usr/sbin/init_resize.sh，写入以下内容：#!/bin/sh reboot_pi () { umount /boot mount / -o remount,ro sync if [ "$NOOBS" = "1" ]; then if [ "$NEW_KERNEL" = "1" ]; then reboot -f "$BOOT_PART_NUM" else echo "$BOOT_PART_NUM" > "/sys/module/${BCM_MODULE}/parameters/reboot_part" fi fi echo b > /proc/sysrq-trigger sleep 5 exit 0 } check_commands () { if ! command -v whiptail > /dev/null; then echo "whiptail not found" sleep 5 return 1 fi for COMMAND in grep cut sed parted fdisk findmnt; do if ! command -v $COMMAND > /dev/null; then FAIL_REASON="$COMMAND not found" return 1 fi done return 0 } check_noobs () { if [ "$BOOT_PART_NUM" = "1" ]; then NOOBS=0 else NOOBS=1 fi } get_variables () { ROOT_PART_DEV=$(findmnt / -o source -n) ROOT_PART_NAME=$(echo "$ROOT_PART_DEV" | cut -d "/" -f 3) ROOT_DEV_NAME=$(echo /sys/block/*/"${ROOT_PART_NAME}" | cut -d "/" -f 4) ROOT_DEV="/dev/${ROOT_DEV_NAME}" ROOT_PART_NUM=$(cat "/sys/block/${ROOT_DEV_NAME}/${ROOT_PART_NAME}/partition") BOOT_PART_DEV=$(findmnt /boot -o source -n) BOOT_PART_NAME=$(echo "$BOOT_PART_DEV" | cut -d "/" -f 3) BOOT_DEV_NAME=$(echo /sys/block/*/"${BOOT_PART_NAME}" | cut -d "/" -f 4) BOOT_PART_NUM=$(cat "/sys/block/${BOOT_DEV_NAME}/${BOOT_PART_NAME}/partition") OLD_DISKID=$(fdisk -l "$ROOT_DEV" | sed -n 's/Disk identifier: 0x\([^ ]*\)/\1/p') check_noobs ROOT_DEV_SIZE=$(cat "/sys/block/${ROOT_DEV_NAME}/size") TARGET_END=$((ROOT_DEV_SIZE - 1)) PARTITION_TABLE=$(parted -m "$ROOT_DEV" unit s print | tr -d 's') LAST_PART_NUM=$(echo "$PARTITION_TABLE" | tail -n 1 | cut -d ":" -f 1) ROOT_PART_LINE=$(echo "$PARTITION_TABLE" | grep -e "^${ROOT_PART_NUM}:") ROOT_PART_START=$(echo "$ROOT_PART_LINE" | cut -d ":" -f 2) ROOT_PART_END=$(echo "$ROOT_PART_LINE" | cut -d ":" -f 3) if [ "$NOOBS" = "1" ]; then EXT_PART_LINE=$(echo "$PARTITION_TABLE" | grep ":::;" | head -n 1) EXT_PART_NUM=$(echo "$EXT_PART_LINE" | cut -d ":" -f 1) EXT_PART_START=$(echo "$EXT_PART_LINE" | cut -d ":" -f 2) EXT_PART_END=$(echo "$EXT_PART_LINE" | cut -d ":" -f 3) fi } fix_partuuid() { mount -o remount,rw "$ROOT_PART_DEV" mount -o remount,rw "$BOOT_PART_DEV" DISKID="$(tr -dc 'a-f0-9' < /dev/hwrng | dd bs=1 count=8 2>/dev/null)" fdisk "$ROOT_DEV" > /dev/null <<EOF x i 0x$DISKID r w EOF if [ "$?" -eq 0 ]; then sed -i "s/${OLD_DISKID}/${DISKID}/g" /etc/fstab sed -i "s/${OLD_DISKID}/${DISKID}/" /boot/cmdline.txt sync fi mount -o remount,ro "$ROOT_PART_DEV" mount -o remount,ro "$BOOT_PART_DEV" } check_variables () { if [ "$NOOBS" = "1" ]; then if [ "$EXT_PART_NUM" -gt 4 ] || \ [ "$EXT_PART_START" -gt "$ROOT_PART_START" ] || \ [ "$EXT_PART_END" -lt "$ROOT_PART_END" ]; then FAIL_REASON="Unsupported extended partition" return 1 fi fi if [ "$BOOT_DEV_NAME" != "$ROOT_DEV_NAME" ]; then FAIL_REASON="Boot and root partitions are on different devices" return 1 fi if [ "$ROOT_PART_NUM" -ne "$LAST_PART_NUM" ]; then FAIL_REASON="Root partition should be last partition" return 1 fi if [ "$ROOT_PART_END" -gt "$TARGET_END" ]; then FAIL_REASON="Root partition runs past the end of device" return 1 fi if [ ! -b "$ROOT_DEV" ] || [ ! -b "$ROOT_PART_DEV" ] || [ ! -b "$BOOT_PART_DEV" ] ; then FAIL_REASON="Could not determine partitions" return 1 fi } check_kernel () { MAJOR="$(uname -r | cut -f1 -d.)" MINOR="$(uname -r | cut -f2 -d.)" if [ "$MAJOR" -eq "4" ] && [ "$MINOR" -lt "9" ]; then return 0 fi if [ "$MAJOR" -lt "4" ]; then return 0 fi NEW_KERNEL=1 } main () { get_variables if ! check_variables; then return 1 fi check_kernel if [ "$NOOBS" = "1" ] && [ "$NEW_KERNEL" != "1" ]; then BCM_MODULE=$(grep -e "^Hardware" /proc/cpuinfo | cut -d ":" -f 2 | tr -d " " | tr '[:upper:]' '[:lower:]') if ! modprobe "$BCM_MODULE"; then FAIL_REASON="Couldn't load BCM module $BCM_MODULE" return 1 fi fi if [ "$ROOT_PART_END" -eq "$TARGET_END" ]; then reboot_pi fi if [ "$NOOBS" = "1" ]; then if ! parted -m "$ROOT_DEV" u s resizepart "$EXT_PART_NUM" yes "$TARGET_END"; then FAIL_REASON="Extended partition resize failed" return 1 fi fi if ! parted -m "$ROOT_DEV" u s resizepart "$ROOT_PART_NUM" "$TARGET_END"; then FAIL_REASON="Root partition resize failed" return 1 fi fix_partuuid return 0 } mount -t proc proc /proc mount -t sysfs sys /sys mount -t tmpfs tmp /run mkdir -p /run/systemd mount /boot mount / -o remount,ro sed -i 's| init=/usr/sbin/init_resize\.sh||' /boot/cmdline.txt sed -i 's| sdhci\.debug_quirks2=4||' /boot/cmdline.txt if ! grep -q splash /boot/cmdline.txt; then sed -i "s/ quiet//g" /boot/cmdline.txt fi mount /boot -o remount,ro sync echo 1 > /proc/sys/kernel/sysrq if ! check_commands; then reboot_pi fi if main; then whiptail --infobox "Resized root filesystem. Rebooting in 5 seconds..." 20 60 sleep 5 else sleep 5 whiptail --msgbox "Could not expand filesystem, please try raspi-config or rc_gui.\n${FAIL_REASON}" 20 60 fi reboot_pi给rootfs/usr/sbin/init_resize.sh赋执行权限：chmod +x rootfs/usr/sbin/init_resize.sh第一次开机执行resize2fs扩容，创建rootfs/etc/init.d/resize2fs_once，写入以下内容：#!/bin/sh ### BEGIN INIT INFO # Provides: resize2fs_once # Required-Start: # Required-Stop: # Default-Start: 3 # Default-Stop: # Short-Description: Resize the root filesystem to fill partition # Description: ### END INIT INFO . /lib/lsb/init-functions case "$1" in start) log_daemon_msg "Starting resize2fs_once" ROOT_DEV=$(findmnt / -o source -n) && resize2fs $ROOT_DEV && update-rc.d resize2fs_once remove && rm /etc/init.d/resize2fs_once && log_end_msg $? ;; *) echo "Usage: $0 start" >&2 exit 3 ;; esac给rootfs/etc/init.d/resize2fs_once赋执行权限：chmod +x rootfs/etc/init.d/resize2fs_once创建rootfs/etc/rc.local，写入以下内容，实现开机自动执行，这里根据自己需求定制：#!/bin/sh -e # #/usr/sbin/gen-server-key # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # exit 0给rootfs/etc/rc.local赋执行权限：chmod +x rootfs/etc/rc.local有了基础系统之后我们chroot进行系统配置，由于我使用的x64平台跟arm64属于异构系统，所以这里要使用qemu进行模拟x64平台：#x64平台进行第二阶段构建 chroot rootfs/ debootstrap/debootstrap --second-stage cp /usr/bin/qemu-aarch64-static rootfs/usr/bin/ #chroot进入基础系统 chroot rootfs/ /usr/bin/qemu-aarch64-static /bin/bash树莓派：#chroot进入基础系统 chroot rootfs/ /bin/bash到这里，我们已经chroot到rootfs目录中了，如果你出现了cannot change locale的错误，没关系，忽略就好了。现在可以对基础系统进行配置了：#添加32位软件支持 dpkg --add-architecture armhf #更新系统软件 apt update apt upgrade #安装基础软件 apt install libc6:armhf apt install locales rng-tools wpasupplicant dhcpcd5 sudo parted apt install net-tools avahi-daemon dphys-swapfile ssh openssh-server apt install htop bash-completion wget curl vim #添加vc-userland支持 echo "/opt/vc/lib/" >/etc/ld.so.conf.d/vc-userland.conf cd /usr/bin/ ; for i in /opt/vc/bin/* ; do ln -sf $i ./ ; done ; cd / #设置swap为1024M #根据自己需求修改 sed -i "s/#CONF_SWAPSIZE=/CONF_SWAPSIZE=1024/g" /etc/dphys-swapfile #设置扩容自动执行 update-rc.d resize2fs_once defaults #设置内核参数 echo -e "kernel.printk = 3 4 1 3\nvm.min_free_kbytes = 16384" > /etc/sysctl.d/98-rpi.conf echo -e "net.core.default_qdisc=fq\nnet.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf #设置时区为上海 ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime #添加wpa_supplicant启动钩子 ln -sf /usr/share/dhcpcd/hooks/10-wpa_supplicant /lib/dhcpcd/dhcpcd-hooks/10-wpa_supplicant #链接wpa_supplicant配置文件到boot分区，这样可以开机前配置wifi ln -sf /boot/wpa_supplicant.conf /etc/wpa_supplicant/wpa_supplicant.conf #设置主机名为raspberrypi echo "raspberrypi" > /etc/hostname echo -e "127.0.0.1\traspberrypi" >> /etc/hosts #配置语言 dpkg-reconfigure locales在弹出窗口用空格选则en_US.UTF-8和zh_CN.UTF-8，然后tab键选择确定：然后选择默认语言，我这里选择en_US.UTF-8，然后tab键选择确定：添加用户：#添加用pi useradd -m -s /bin/bash pi #设置密码，输入两次确认 passwd pi #给pi添加sudo权限 echo "pi ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/00_pi如果需要开启root用户ssh登录可以这样操作，不需要的可以忽略：#修改root密码，输入两次确认 passwd #开启root ssh登录 sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config基本配置完成，下面配置一些定制内容，可以根据自己需求来，不需要的可以忽略：#安装Git、python3 apt install git python3 python3-pip #添加python3的gpio库 pip3 install RPi.GPIO镜像定制的需求在这里自由发挥，发挥完以后退出chroot环境：sync exit #清除日志 echo > rootfs/root/.bash_history sync三、boot分区文件准备现在开始准备boot分区的文件：#拷贝BootLoader cp rpi-firmware/bootcode.bin rpi-firmware/fixup* rpi-firmware/start* boot/执行blkid /dev/mapper/loop10p2，其中loop10p2替换为自己的设备名称，根据结果替换下面root=PARTUUID=的值。创建boot/cmdline.txt，内容如下：dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=ec5f336e-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait init=/usr/sbin/init_resize.sh创建boot/config.txt，内容如下：# For more options and information see # http://rpf.io/configtxt # Some settings may impact device functionality. See link above for details arm_64bit=1 # uncomment if you get no picture on HDMI for a default "safe" mode #hdmi_safe=1 # uncomment this if your display has a black border of unused pixels visible # and your display can output without overscan #disable_overscan=1 # uncomment the following to adjust overscan. Use positive numbers if console # goes off screen, and negative if there is too much border #overscan_left=16 #overscan_right=16 #overscan_top=16 #overscan_bottom=16 # uncomment to force a console size. By default it will be display's size minus # overscan. #framebuffer_width=1280 #framebuffer_height=720 # uncomment if hdmi display is not detected and composite is being output #hdmi_force_hotplug=1 # uncomment to force a specific HDMI mode (this will force VGA) #hdmi_group=1 #hdmi_mode=1 # uncomment to force a HDMI mode rather than DVI. This can make audio work in # DMT (computer monitor) modes #hdmi_drive=2 # uncomment to increase signal to HDMI, if you have interference, blanking, or # no display #config_hdmi_boost=4 # uncomment for composite PAL #sdtv_mode=2 #uncomment to overclock the arm. 700 MHz is the default. #arm_freq=800 # Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on # Uncomment this to enable the lirc-rpi module #dtoverlay=lirc-rpi # Additional overlays and parameters are documented /boot/overlays/README # Enable audio (loads snd_bcm2835) dtparam=audio=on [pi4] # Enable DRM VC4 V3D driver on top of the dispmanx display stack dtoverlay=vc4-fkms-v3d max_framebuffers=2 [all] #dtoverlay=vc4-fkms-v3d 创建boot/wpa_supplicant.conf，实现开机前配置wifi，内容如下：ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 country=CN network={ ssid="wifi名称" psk="wifi密码" key_mgmt=WPA-PSK priority=1 }如果不需要配置wifi，在上面文件每一行前面加一个#注释掉即可。四、内核构建树莓派开机logo也是在内核中修改，需要的可以参考下文https://linuxer.top/archives/replace-raspi-logo.html现在开始内核编译，首先clone官方内核代码到本地：#安装git apt install git #clone代码 #我们clone默认分支，版本是4.19.y #需要其他分支 添加 -b 分支名称 git clone --depth=1 https://github.com/raspberrypi/linux修改EXTRAVERSION实现自定义内核版本号，修改linux/Makefile文件第5行：EXTRAVERSION = -kevin这样内核的版本显示为4.19.y-kevin，这里根据自己需求修改。开始编译，如果使用x64请参考1、交叉编译，使用树莓派编译请参考2、树莓派编译。1、交叉编译#配置交叉编译环境 apt install build-essential gcc-aarch64-linux-gnu bc bison flex libssl-dev make libc6-dev libncurses5-dev #进入源码目录 cd linux #配置内核 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig #如果想对内核做一些配置可以执行此命令 #在弹出框里可以配置内核各种参数 #这里不做展开，相关资料自行查阅 #保持默认参数可以跳过此命令 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig #开始编译 #这里会花费一定的时间，具体看你电脑配置 #-j4 后面的4可以改成cpu核心数加快编译 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j4 #安装内核模块 make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=../rootfs modules_install #拷贝内核到boot分区 cp arch/arm64/boot/Image ../boot/kernel8.img #拷贝dtb到boot分区 cp arch/arm64/boot/dts/broadcom/*.dtb ../boot/ #拷贝overlays到boot分区 cp -r arch/arm64/boot/dts/overlays/ ../boot/2、树莓派编译使用树莓派编译时cpu几乎会满载，如果你有其他服务正在运行，建议先停掉。配置编译环境：apt install tmux build-essential bc bison flex libssl-dev make libc6-dev libncurses5-dev如果你树莓派是ssh登录的，我强烈建议你使用tmux或者screen创建新会话来编译，我这里选择tmux:#进入源码目录 cd linux #创建新会话kernel tmux new -s kernel #配置内核 make ARCH=arm64 bcm2711_defconfig #如果想对内核做一些配置可以执行此命令 #在弹出框里可以配置内核各种参数 #这里不做展开，相关资料自行查阅 #保持默认参数可以跳过此命令 make ARCH=arm64 menuconfig #开始编译 #这里会花费很长时间，可以出去休息一会 #我用4b4g大约90分钟左右 make ARCH=arm64 -j4 #退出tmux exit #安装内核模块 make ARCH=arm64 INSTALL_MOD_PATH=../rootfs modules_install #拷贝内核到boot分区 cp arch/arm64/boot/Image ../boot/kernel8.img #拷贝dtb到boot分区 cp arch/arm64/boot/dts/broadcom/*.dtb ../boot/ #拷贝overlays到boot分区 cp -r arch/arm64/boot/dts/overlays/ ../boot/ #如果ssh连接断开可以重新连接切换到root执行以下命令重连 #编译过程不会中止 #没断开自然更好，可以忽略此命令 tmux attach -t kernel至此内核编译完成。五、收尾最后做一些收尾工作：cd ../ sync #卸载镜像分区挂载 umount boot/ umount rootfs/ #注意/dev/loop10改为自己的挂载设备 kpartx -d /dev/loop10 losetup -d /dev/loop10 到这里我们的镜像就算做好了，兼容3B、3B+、4B，现在把buster.img刷到卡上验证一下。2020年初就想总结一下，一拖拖了半年了，终于写完了，一身轻松~~都是野路子让大佬们见笑了~本文为原创文章，版权归 Kevin's Blog 所有，转载请联系博主获得授权。
MySQL是一款非常优秀的关系型数据库，因为其速度、可靠性和适应性而备受关注，很多大型网站都是用Mysql作为数据存储，今天讲一下如何在树莓派上安装mysql5.7。数据无价，本教程的操作有一定的风险，开始前请备份重要数据！！！正式开始之前先要说一下MySQL与MariaDB的关系。随着Oracle收购Sun公司，MySQL也归到了Oracle的名下，MySQL之父的Michael在意识到MySQL有闭源风险之后，新开了一个分支，作了部分修改，形成了MariaDB。互联网用户以及Linux发行商纷纷抛弃MySQL，转投MariaDB阵营，Debian从9开始也用MariaDB替换了MySQL，所以我们现在不能直接在apt的源中安装MySQL。MariaDB初期和MySQL可以说是在代码级兼容的，但是随着各自分支的发展和新特性的加入，不兼容的地方会越来越多，我强烈建议在项目一开始就选择好数据库，否则后期迁移数据也是个头疼的事。如果选择MariaDB，执行apt update && apt install mariadb-server，搞定，后面可以忽略了，教程结束。选择MySQL请继续阅读先做准备工作：#切换到root用户 sudo -i #升级系统 apt update apt upgrade如果你是32系统，例如官方32系统：wget https://linuxer.top/usr/uploads/2020/06/mysql57_armhf.tar.gz #解压 tar -zxvf mysql57_armhf.tar.gz cd mysql57_armhf/ apt install ./*.deb #安装完成，检查mysql版本 mysql -V如果你是64位系统，例如基地2.0、官方64位系统或其他64位自制Debian：wget https://linuxer.top/usr/uploads/2020/06/mysql57_arm64.tar.gz #解压 tar -zxvf mysql57_arm64.tar.gz cd mysql57_arm64/ apt install ./*.deb #安装完成，检查mysql版本 mysql -Vroot密码默认为空，可以执行mysql_secure_installation进行初始化配置。这是基地2.0系统的安装效果MySQL的各种配置这里不讲了，需要改的东西大家自己百度就ok，资料很多的。如果是想配置lnmp环境又不想自己折腾，可以从这里下载配置好宝塔镜像，刷到卡里就能用，非常方便。本文为原创文章，版权归 Kevin's Blog 所有，转载请联系博主获得授权。
宝塔面板是一款使用方便、功能强大且终身免费的服务器管理软件,支持Linux与Windows系统。一键配置:LAMP/LNMP、网站、数据库、FTP、SSL,通过Web端轻松管理服务器。该面板可以运行在树莓派上，但是由于软件都是编译安装，耗时长且容易出错，为了方便大家使用，我制作了一个配置好宝塔环境的镜像，有需要的朋友可以下载使用。镜像说明这个镜像是基于Debian10(buster)的arm64系统,内核版本为4.19.97，宝塔版本为7.2.0，（2020-09-05日更新版升级内核为5.4.51,升级宝塔版本为7.4.5），已更换清华源，已更新最新BootLoad，可以刷到USB设备启动，USB启动设置请参考这里或者这里，如果需要迁移到移动硬盘请参考这里。兼容3B、3B+、4B。此镜像无桌面环境，默认开启ssh服务，支持开机前配置wifi，方法为修改boot分区wpa_supplicant.conf文件。根据需要配置一个或多个wifi连接信息，去掉network块前的#，将ssid和password替换为真实值即可。示例：ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 country=CN network={ ssid="无线ssid" psk="无线密码" key_mgmt=WPA-PSK priority=1 } 默认用户/密码：pi/raspberry，root用户没有启用，如果需要请自行开启。如果刷入到SD卡或U盘中，需要手动扩容，方法为：sudo resize.root7.4.5版本自动扩容，无需手动操作！默认swap大小为200M，如需修改，请编辑/etc/dphys-swapfile文件，修改CONF_SWAPSIZE=200，单位为MB，如果需要设置1G，则配置为CONF_SWAPSIZE=1024，保存文件执行sudo systemctl restart dphys-swapfile.service重启服务即可。面板为纯净面板，安装软件如下：面板操作方法：sudo bt根据需要选择功能并输入对应编号即可，上图输入14为获取面板信息，这里可以获取面板默认安全入口和默认用户名密码，登录之后请立即修改密码和安全入口地址！！我部署了一个typecho测试，功能正常这里提供两个版本的下载，python2和python3，宝塔官方说py3版本可能存在少量兼容问题，但是实际使用过程中没有发现明显区别，建议选择py3版本，毕竟py2已经寿终正寝了。2020-09-05更新内核升级到5.4.51宝塔版本升级到7.4.5增加自动扩容功能，第一次启动自动扩容，无需手动操作下载地址下载地址：https://pan.baidu.com/s/1kQfw4hTUjOVaDtcHf4ekdQ ，提取码：ltiu文件说明：bt-7.2.0-py2-buster-aarch64.img.xz，宝塔7.2.0，内核4.19.97，python2bt-7.2.0-py3-buster-aarch64.img.xz，宝塔7.2.0，内核4.19.97，python3bt-7.4.5-py3-buster-aarch64.img.xz，宝塔7.4.5，内核5.4.51，python3，强烈推荐本文为原创文章，版权归 Kevin's Blog 所有，转载请联系博主获得授权。
之前的文章介绍了4B设置USB启动的方法和系统迁移到USB设备的方法，主要思路就是生成当前系统的最小备份镜像然后将镜像刷入USB设备，这样做对于U盘这样的设备还是很好的，但是对于大容量的移动硬盘是不适用的，镜像刷入硬盘后，之前的分区和数据都会被覆盖。这篇文章就讲一下如何在保留硬盘数据的情况下迁移树莓派系统。数据无价，本教程的操作有一定的风险，开始前请备份重要数据！！！本教程兼容官方系统、基地2.0系统、Ubuntu。这篇文章只讲系统迁移，USB启动设置请参考这里或者这里。想让树莓派正常启动至少需要两个分区，一个FAT32分区，一个ext4分区(f2fs、btrfs也可以，看自己需要)，FAT32分区存放BootLoader、内核、配置文件等，ext4分区为roofs挂载为根节点。我们现在要调整硬盘，把这两个分区规划出来，FAT32分区大小256M足够了多了没用，ext4分区看自己需求，建议16g以上。使用工具为DiskGenius。打开DiskGenius，可以看到我这块硬盘目前有三个分区：我的规划是留三个150G分区，剩下的用来迁移系统，这里注意一下，FAT32分区最好是整个磁盘第一个分区，ext4分区无所谓，所以这里调整第一个分区，在前面划出一部分空间备用，在第一分区上点击右键，选择调整分区大小在弹出对话框中改变分区大小，让分区前出现空闲空间:执行完之后的分区如下：在空闲分区处新建一个NTFS分区并设置为主分区，然后保存更改：我要迁移的系统是无桌面的，所以15G是完全够用的。现在磁盘的调整已经完成，下面的操作在树莓派上进行，把要迁移的SD卡插到树莓派上启动，然后将调整好的硬盘插到USB接口上。后面的操作都需要root权限，执行sudo -i切换到root用户：#切换到root sudo -i #查看磁盘情况 lsblk可以看到我的硬盘设备为sda，下面对sda进行分区操作，创建FAT32和ext4分区：#使用cfdisk操作硬盘 #操作时根据具体情况将/dev/sda替换为自己的设备 cfdisk /dev/sda用上下方向键选择我们创建的15.8G的NTFS分区，用左右按键选择Delete操作，然后回车：然后创建FAT32分区，用上下方向键选择调整出来的Free space,用左右按键选择New操作，然后回车：输入分区大小：256M，回车，然后上下键选择刚创建的分区，左右键选择Type操作，回车，选择类型c，回车：然后创建ext4分区，用上下方向键选择Free space,用左右按键选择New操作，回车，使用默认大小，回车：然后用左右按键选择Write操作，弹出提示输入yes,回车后按q退出：磁盘的准备工作已经完成了，现在开始迁移系统。先执行lsblk查看我们新建的分区：从输出我们可以看出两个分区分区别为sda1(FAT32)和sda3(ext4)，现在开始格式化分区：#更新源 apt update #安装需要的软件 apt install -y dosfstools rsync #格式化FAT32分区 #根据实际情况替换/dev/sda1为自己的设备 mkfs.vfat -F 32 -n `dosfslabel /dev/mmcblk0p1 | tail -n 1` /dev/sda1 #格式化ext4分区 #根据实际情况替换/dev/sda3为自己的设备 mkfs.ext4 /dev/sda3 e2label /dev/sda3 `e2label /dev/mmcblk0p2 | tail -n 1`现在迁移boot分区：#挂载sda1到/mnt/ #根据实际情况替换/dev/sda1为自己的设备 mount /dev/sda1 /mnt/ #拷贝boot分区文件 cp -rf `findmnt -n /dev/mmcblk0p1 | awk '{print $1}'`/* /mnt/拷贝完boot分区文件后，要替换cmdline.txt中的PARTUUID：执行blkid，找到sda3的PARTUUID(根据自己情况确定PARTUUID)编辑/mnt/cmdline.txt文件，将root=PARTUUID=xxx中的xxx替换自己的执行结果，我的修改结果为root=PARTUUID=a8bf0107-03。如果是ubuntu系统，这步可以忽略。同步根分区：cd #同步磁盘 sync #反挂载/mnt umount /mnt #挂载sda3到/mnt/ #根据实际情况替换/dev/sda3为自己的设备 mount /dev/sda3 /mnt/具体的同步工作需要写一个脚本来操作，创建文件syncrootfs.sh，内容如下：#!/bin/bash boot_mnt=`findmnt -n /dev/mmcblk0p1 | awk '{print $1}'` rsync --force -rltWDEgop --delete --stats --progress \ --exclude ".gvfs" \ --exclude "$boot_mnt" \ --exclude "/dev" \ --exclude "/media" \ --exclude "/mnt" \ --exclude "/proc" \ --exclude "/run" \ --exclude "/snap" \ --exclude "/sys" \ --exclude "/tmp" \ --exclude "lost\+found" \ / /mnt if [ ! -d $boot_mnt ]; then mkdir $boot_mnt fi if [ -d /snap ]; then mkdir /mnt/snap fi for i in boot dev media mnt proc run sys boot; do if [ ! -d /mnt/$i ]; then mkdir /mnt/$i fi done if [ ! -d /mnt/tmp ]; then mkdir /mnt/tmp chmod a+w /mnt/tmp fi sync执行文件bash syncrootfs.sh，脚本会花费一定的时间，具体时间看迁移系统的大小，执行成功后如下图：替换fstab文件中的PARTUUID，编辑/mnt/etc/fstab文件，将/boot和/对应的PARTUUID修改为sda1和sda3对应的PARTUUID。如果是ubuntu系统，这步可以忽略。执行blkid：我修改后的结果为：把改变同步到磁盘中：cd #同步磁盘 sync #反挂载/mnt umount /mnt把硬盘插到电脑上，替换最新BootLoader，地址：https://github.com/Hexxeh/rpi-firmware,下载zip包，解压后把里面的fixup*.dat和star*.elf文件拷贝到硬盘256M的FAT32分区替换原文件。取下树莓派的SD卡，插上移动硬盘，上电。启动后查看磁盘信息lsblk:如果希望数据盘自动挂载，自行修改/etc/fstab文件，这里不做说明。本文为原创文章，版权归 Kevin's Blog 所有，转载请联系博主获得授权。
上一篇文章介绍了官方系统设置USB启动的方法，这篇文章讲一下树莓派爱好者基地2.0系统设置USB启动的方法，使用镜像为无桌面增强版(2019-12-30-OPENFANS-Debian-Buster-Aarch64-ext4-v2019-2.0-U2-Release-plus++)。其实主要区别就在更新eeprom这一步，后面USB启动介质的制作是没有区别的。如果你只有一张卡，或者不想再刷个官方系统，那么可以参考这篇文章。数据无价，本教程的操作有一定的风险，开始前请备份重要数据！！！基地2.0系统做的非常完善，已经添加了rpi-eeprom的支持，但是由于版本太老，并不能使用最新的固件，所有我们要借助官方的rpi-eeprom项目来获取最新固件。整个过程都需要root权限，如果你是用pi用户登录的，先执行sudo -i切换到root用户。#卸载旧版rpi-eeprom apt remove rpi-eeprom rpi-eeprom-images #clone最新版本到本地 git clone https://github.com/raspberrypi/rpi-eeprom /usr/local/rpi-eeprom #将eeprom版本设置为beta版 echo 'FIRMWARE_RELEASE_STATUS="beta"' > /etc/default/rpi-eeprom-update执行完上述操作后，将/usr/local/rpi-eeprom和/usr/local/rpi-eeprom/firmware加入到PATH中，操作如下，编辑文件/etc/profile，在文件最后添加如下内容:export PATH=/usr/local/rpi-eeprom:/usr/local/rpi-eeprom/firmware:$PATH保存文件后执行下列语句使PATH生效source /etc/profile现在可以升级eeprom了。如果想用固件的默认配置直接执行rpi-eeprom-update -d -a，然后重启完成升级。如果想修改eeprom的参数配置，请参考这里。如果官方发布了新的固件，更新固件的方法为：#打开项目地址 cd /usr/local/rpi-eeprom #拉最新代码 git pull #升级固件 rpi-eeprom-update -d -aeeprom升级完成，下面讲一下如何把SD卡里的系统迁移到USB设备。执行sudo -i切换到root用户制作SD卡最小镜像：git clone https://github.com/nanhantianyi/rpi-backup cd rpi-backup/ #根据实际情况选择镜像的保存位置(具体参考README.md文件) #我这里备份到我的U盘中，挂载路径为/media ./back.sh /media/rpi-back.img上面的命令会给当前系统做一个备份并生成一个镜像，名字为rpi-back.img，这会花费一定时间，具体时间取决于你系统的已用的空间，耐心等待一会。备份成功后将rpi-back.img文件拷贝到电脑，用软件把镜像烧到U盘中，如果不想迁移SD卡数据，可以忽略备份这个步骤，直接将2.0系统镜像刷到U盘中，不管是刷备份镜像还是直接刷系统镜像，都要替换BootLoader，地址：https://github.com/Hexxeh/rpi-firmware,下载zip包，解压后把里面的fixup*.dat和star*.elf文件拷贝到U盘覆盖原文件。好了，现在取出SD卡，插上U盘，加电，USB启动成功。如果是刷的备份镜像，还需要手动扩容一下#切换到root sudo -i #扩容rootfs resize.root好了，USB启动成功！本文为原创文章，版权归 Kevin's Blog 所有，转载请联系博主获得授权。