章节 内容
编译 LEDE 配置编译环境,配置编译,编译 LEDE
编译时故障 在编译时可能遇上的故障
使用时故障 在使用时可能遇上的故障
文件系统相关 一些其他的问题
eMMC 写入 写入 eMMC

环境参考

  • Ubuntu 20

    建议 Ubuntu 或者 Debian 系的系统进行编译,方便解决依赖问题

  • 云服务器

    下载依赖速度快,优先推荐海外的(带宽充足)
    2 x Intel® Xeon® Gold 6133 CPU @ 2.50GHz
    4GB Memory

  • Windows 11 Build 10.0.22621

    只要有 openssh,都行

编译 LEDE

环境准备

  1. 不建议使用 root 来编译,容易发生很多魔法问题
  2. 建议采用全新环境编译,避免遇上魔法问题
  3. 不建议使用中文编码环境编译,避免遇上魔法问题
  4. 魔法问题,就是虽然有办法应对,可以简单解决就不要复杂化的问题

一般 VPS 为了图省事,都会安装只有 root 用户的系统,但 lede 这里不能用 root 用户,需要重新创建一个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 查看当前是否为 root
id
#uid=0(root) gid=0(root) groups=0(root)

# 给当前用户创建密码
#passwd
# 如果后面 sudo 提示需要密码,请在 root 用户下运行此命令

# 切换到 root 用户
# su root

# 部分采用 root 用户,需要新建一个 用户来编译,这里以 lede 为例
useradd -r -m -s /bin/bash lede

# 给用户 lede 创建密码
passwd lede

# ======= lede 用户下执行命令 =======
# 进入 lede 用户
su lede

# 进入用户目录
cd ~
# ======= lede 用户下执行命令 =======

# 锁定用户 lede
passwd lede –l
# 释放用户 lede
passwd lede –u
# 删除用户 lede
userdel -r lede

依赖库比较多,在服务器里面可以开个 Ubuntu 的 Docker 镜像专门用来编译,防止破坏环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#换源
#sudo sed -i 's|deb.debian.org|mirrors.cloud.tencent.com|g' /etc/apt/sources.list

# 更新软件源
sudo apt update

# 更新软件
#sudo apt upgrade

# 安装 screen
sudo apt install -y screen

# 启用 screen
screen -S
# 挂回 openwrt
#screen -d openwrt

# 安装编译依赖
#sudo apt install -y ack antlr3 asciidoc autoconf automake autopoint binutils \
# bison build-essential bzip2 ccache cmake cpio curl \
# device-tree-compiler fastjar flex gawk gettext \
# gcc-multilib g++-multilib git gperf haveged help2man \
# intltool libc6-dev-i386 libelf-dev libglib2.0-dev \
# libgmp3-dev libltdl-dev libmpc-dev libmpfr-dev \
# libncurses5-dev libncursesw5-dev libreadline-dev \
# libssl-dev libtool lrzsz mkisofs msmtp nano ninja-build \
# p7zip p7zip-full patch pkgconf python2.7 python3 \
# python3-pyelftools libpython3-dev qemu-utils rsync scons \
# squashfs-tools subversion swig texinfo uglifyjs upx-ucl \
# unzip vim wget xmlto xxd zlib1g-dev python3-setuptools

# 设置时区
sudo timedatectl set-timezone 'Asia/Shanghai'

dependencies=(ack antlr3 asciidoc autoconf automake autopoint binutils bison
build-essential bzip2 ccache cmake cpio curl device-tree-compiler
fastjar flex gawk gettextgcc-multilib g++-multilib git gperf
haveged help2man intltool libc6-dev-i386 libelf-dev libglib2.0-dev
libgmp3-dev libltdl-dev libmpc-dev libmpfr-devlibncurses5-dev
libncursesw5-dev libreadline-dev libssl-dev libtool lrzsz mkisofs
msmtp nano ninja-build p7zip p7zip-full patch pkgconf python2.7
python3 python3-pyelftools libpython3-dev qemu-utils rsync scons
squashfs-tools subversion swig texinfo uglifyjs upx-ucl
unzip vim wget xmlto xxd zlib1g-dev python3-setuptools
)
for dependency in "${dependencies[@]}"; do
sudo apt-get install -y "$dependency"
done6

如果在安装依赖,或者下面步骤关闭了终端,或者丢失了连接,都可以通过下面命令连回,并且不会中断命令执行。

1
screen -r openwrt

源码准备

源码准备需要连接 GitHub,最好在出海带宽富裕的时候使用(10MB/s)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 拉取源码
git clone https://github.com/coolsnowwolf/lede

cd lede/

# 编辑 feeds.conf
# 可以去掉注释或者添加新的 feed,里面是一些配置好的软件和驱动
vi feeds.conf.default

# 也可以追加一些源
cat >> feeds.conf.default <<EOF
src-git kenzo https://github.com/kenzok8/openwrt-packages
src-git nas https://github.com/linkease/nas-packages.git
src-git jerrykuku https://github.com/jerrykuku/openwrt-package
EOF

# 更新 feeds 源
./scripts/feeds update -a

# 安装 feeds 源
./scripts/feeds install -a

# 修改默认主题
sed -i 's|luci-theme-bootstrap|luci-theme-argon|' feeds/luci/collections/luci/Makefile

# 修改作 LAN 口 IP
sed -i 's|192.168.1.1|10.0.0.1|g' package/base-files/files/bin/config_generate

# 修改主机名
sed -i 's|OpenWrt|mywrt|g' package/base-files/files/bin/config_generate

# 修改为中国标准时区
sed -i 's|UTC|CST|g' package/base-files/files/bin/config_generate

编译目标配置

1
make menuconfig

需要从上到下配置的为以下几个选项,后面几个是需要添加进去的软件包,可以根据实际情况添加。

原文 解释
Target System 编译目标架构(处理器厂商)
Subtarget 细分处理器类型
Target Profile 细分硬件类型(用在什么板子上)
Target Images 编译生产的镜像格式/打包方式
Firmware 硬件驱动
Development 开发工具(gcc)
Languages 开发语言(Python)
Libraries 依赖库(加密解密库)
LuCI [重点] LuCI 的一大堆东西,插件
Multimedia 媒体解码器( FFmpeg)
Network 网络相关的各种软件
Sound 音频解码器
Utilities 系统工具

关于 LuCI 这一部分,进入 LuCI --> Applications 可以自定义更多的插件

配置完记得选择 Save 保存为 .config 保存好。

配置完成后需要下载编译目标所需的 dll 库:

1
2
# V=s 是 openwrt 需要的参数,建议 8 线程以缓解服务器压力
make -j8 download V=s

编译

一般比较久,1h 起步,对于云服务器务必采用 screen 防止意外断流带来的编译中断。

1
2
3
4
5
6
7
# 非 root 用户
make -j$(nproc) V=s
# root 用户
#make FORCE_UNSAFE_CONFIGURE=1 -j$(nproc) V=s

# 找到到编译目标
cd bin/targets/

编译完成后在 bin/targets/ 下可以找到对应的编译目标

文件名 说明 用途
xxx-generic-squashfs-combined.img.gz 带引导分区文件 直接刷入
xxx-generic-squashfs-combined.vmdk 带引导分区的 Vmware 虚拟磁盘 虚拟机
xxx-rootfs-squashfs.img.gz 分区文件,无引导 升级
xxx-generic-squashfs-combined-efi.img.gz 带 EFI 引导分区文件 直接刷入
xxx-ext4-combined.img.gz ext4 分区文件,无引导 升级
xxx-combined-squashfs.iso 镜像 直接刷入

注意,这里的 img.gz 后缀均为压缩文件,需要解压缩后刷入系统

1
2
3
4
# 解压后会删除原文件
gzip -d *.img.gz
# 解压后不删除原文件
gzip -dk *.img.gz

二次编译

一次编译好后在第二次会根据配置的 .conf 进行编译,可以设置定时任务每天编译。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 更新
cd lede/

# Git 仓库更新
git pull

# 订阅包源更新
./scripts/feeds update -a

./scripts/feeds install -a

# 清理旧文件
#make clean

# 下载源码
make -j8 download V=s

# 编译
make -j$(nproc) V=s

使用 Action 编译

Github Action 进行云构建
https://github.com/P3TERX/Actions-OpenWrt/generate

当然还有一种玩法就是用 act 进行本地构建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
curl -s https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash

# 丢进 /usr/bin 里面
sudo cp /bin/act /usr/bin/act

# 删除
# sudo rm -f /usr/bin/act

# 下载 LEDE Action 项目
git clone https://github.com/P3TERX/Actions-OpenWrt/tree/main

# 查看所有能编译的项目
act -l
#Stage Job ID Job name Workflow name Workflow file Events
#0 build build Build OpenWrt build-openwrt.yml repository_dispatch,workflow_dispatch
#0 check check Update Checker update-checker.yml workflow_dispatch

# 构建
act workflow_dispatch

编译时故障

网络问题

  • 自己想办法
  • 等出海带宽闲置时候拉取源码
  • 用云服务器
  • 用 Github Action 编译

root 下编译失败

无视不安全配置

1
make FORCE_UNSAFE_CONFIGURE=1 -j$(nproc) V=s

这会导致编译出来的源码权限混乱,因此不建议用 root 权限编译,会带来极大的安全风险。

重新配置 feeds 后编译错误

清理掉 feeds 重新下载,重新编译

1
2
3
./scripts/feeds clean
./scripts/feeds update -a
./scripts/feeds install -a

更换目标架构/出错

需要清理目录

1
make dirclean

或者删除目录重新下载

内存不足

out of memory

  • 加内存
  • 换大内存服务器
  • 加 swapfile

添加 swapfile 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 创建 1024M 的 /swapfile
sudo fallocate -l 1024M /swapfile

# 仅所有者可写
sudo chmod 600 /swapfile

# 格式化为交换分区
sudo mkswap /swapfile

# 启用交换分期
sudo swapon /swapfile
# Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
#no label, UUID=220bf9b2-9099-4a4d-b157-bd7f5665f146

# 交换分区大小
#ls -l / | grep swap
#-rw------- 1 root root 1.0G 2023-08-02 10:41 swapfile

# 设置系统启动自动挂载
sudo echo '/swapfile none swap defaults 0 0' >> /etc/fstab

# 确认交换分区情况
cat /proc/swaps
cat /proc/meminfo | grep Swap

# ======== 以下是删除 ========

# 删除开机挂载
sed -i '|swapfile|d' /etc/fstab

# 卸载交换分区
sudo swapoff /swapfile

# 卸载所有交换分区
#sudo swapoff -a

# 删除文件
sudo rm -f /swapfile

提示:在 WSL 下需要将主机的 Chromium 内核的软件全部关闭,以确保能编译成功。 很多次遇上 WSL 里面的编译错误,都是因为主机内存被 Chromium 大量占用。

大小不兼容问题

编译时提示不兼容大小写不敏感系统

1
Build dependency: OpenWrt can only be built on a case-sensitive filesystem

常见于 Windows 下进行编译,不要跨文件系统运行,因为 Windows 的文件系统是大小写不敏感的,Linux 的文件系统是大小写敏感的。

常见于 WSL 时又喜欢敲完 wsl 直接回车,编译时目录都在 Windows 的 NTFS 文件系统下

1
2
PS C:\Users\0xac> wsl
/mnt/c/Users/0xac >

实际工作目录是在主机的用户目录下,自然容易遇到很多奇怪的问题,只需要切换到用户目录下即可:

1
2
3
> cd ~
> pwd
/home/aero

使用时故障

镜像空间不足

驱动/包多时,会占用大量空间,需要扩大镜像的空间

make menuconfig 中调整

1
2
Target Images ---> (16) Kernel partition size (in MB)
Target Images ---> (160) Root filesystem partition size (in MB) (512)

Kernel partition size (内核分区)扩大到 256MB
Root filesystem partition size (根文件分区)扩大到 512MB

IPv6 支持

make menuconfig 中勾选

1
Extra packages ---> ipv6helper

或者勾选:

1
2
3
4
Network  --->  odhcp6c
Network ---> odhcpd-ipv6only
LuCI ---> Protocols ---> luci-proto-ipv6
LuCI ---> Protocols ---> luci-proto-ppp

刷固件后用不了 Wifi

无法识别 Wifi 网卡,需要确认 Firmware 中的 对应 网卡驱动是否勾上

换源

需要先配置好 ssl 相关套件

1
2
3
4
opkg update
opkg install ca-certificates luci-ssl-openssl

sed -i 's|downloads.openwrt.org|mirrors.cloud.tencent.com/lede|' /etc/opkg/distfeeds.conf

文件系统相关

大文件上传

一般 lede 的 WebUI 中上传超过 2GB 的文件都不怎么稳定,推荐使用 ssh 协议下的 scp 进行上传:

1
scp ./230513.img.tar.gz [email protected]:~/230513.img.tar.gz

上传写入 eMMC

对于某些板子上带有 eMMC 的,使用 LEDE 的网页写入容易出现故障,这里可以采用手动写入的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 本地,上传 img
scp ./230513.img.tar.gz [email protected]:~/230513.img.tar.gz

# 下面进入远端

# 解压镜像
tar -vxf 230513.img.tar.gz

# 查看分区情况,一般从 TF 卡启动 0号是 TF卡,1号才是 eMMC
lsblk
#fdisk -l

# 分区表,变更为 gpt,注意 /dev/mmcblk1 目标不要搞错
parted /dev/mmcblk1 mklabel gpt

# 格式化分区,变更为 ext4
parted /dev/mmcblk1 mkpart sub ext4 0% 100%

# 查看分区情况,格式化后应该会变
lsblk

# 写入 img
dd if=/230513.img of=/dev/mmcblk1 bs=1M conv=sync status=progress

# 刷新设备
partprobe /dev/mmcblk2

# 查看对应的分区是否符合预期
lsblk

分区拓展

实际上非常简单,对于有连续未使用的空间,都可以拓展上去

1
2
3
4
5
6
7
8
# 注意找到对应的分区
lsblk

# 注意,最大那个分区一般就是系统分区,索引为 2
parted /dev/mmcblk2 2 100%

# 拓展文件系统到当前内核上
resize2fs /dev/mmcblk2

这种方法是无损的,不需要关闭当前系统,然后挂上另外一个系统,进行操作的

文件损坏

报错: Read Only File system

多出现于宿舍这种经常断电的地方,从结果上看,基本上是:

  1. 文件系统错误
  2. 硬件故障
  3. 只读挂载

说人话就是是:

  1. 经常断电,拔电式关机,导致文件数据出错
  2. 软件编写有问题,写坏文件系统
  3. 脑子抽了,写了成只读

只读挂载

如果挂载为只读,只需要重新以可读写方式挂载。

1
2
3
4
5
6
# 找到对于的目录
mount | grep /dev/sda1
#/dev/sda1 on /mnt/sda1 type ext4 (rw,relatime,stripe=8191)

# 重新挂载
mount -o remount,rw /dev/sda1

但这对 / 根目录没有用,因为一般 根目录只读,都是文件系统故障,需要用命令进行修复。

修复文件系统

对于文件系统损坏,可以修复文件系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 检测系统日志,寻找报错点
dmesg |egrep "ext[2..4]|xfs"
# 找不到没关系

# 找到 / 根目录 或者队友损坏目录 的设备
lsblk

# 修复根目录挂载的设备,注意是设备,在 /dev/ 下的,不是挂载的目录
fsck.ext4 -y /dev/mmcblk1p2
#fsck.ext3 -y /dev/mmcblk1p2
#fsck.ext2 -y /dev/mmcblk1p2
# 这里要注意文件系统

# 刷新存储设备
partprobe /dev/mmcblk1

# 如果刷新没有用,需要重启
reboot -f

写入 eMMC

写入 eMMC 分四步走:

  1. 外部引导进入系统,比方说从 TF 卡启动(具体启动方法见厂商)
  2. 刷入 .img 镜像
  3. 调整分区
  4. 拔卡重启

外部引导进入系统

  1. 一部分设备有 MASK 按键,上电同时长按 5s 以上,10s 以下,就能强制从 TF 卡(TF 卡需要刷好系统镜像)引导。

倘若不知道系统是否正常启动,可以使用调试器,接入设备上的串口。查看从上电开始的命令行输出是否正常。

  1. 可以直接破坏 eMMC 分区,导致系统只能从 TF 卡引导启动:
1
dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=1 status=progress

上传并写入系统镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 上传 img
scp sysupgrade.img [email protected]:/sys.img

# 查看分区情况,一般从 TF 卡启动 0号是 TF卡,1号才是 eMMC
lsblk
#fdisk -l
#mmcblk1 179:32 0 28.9G 0 disk

# 解挂载与 mmcblk1 相关的所有分区
umount $(mount | grep /dev/mmcblk1 | awk '{print $3}')

# 重建分区表
parted /dev/mmcblk1 mklabel gpt
# 重建

# 格式化
parted /dev/mmcblk1 mkpart sub ext4 0% 100%
# 这里不需要 4k 对其,因为写入镜像后分区会改变

# 查看分区情况,格式化后应该会变
lsblk

# 写入 img
dd if=/sys.img of=/dev/mmcblk1 bs=1M conv=sync status=progress

调整分区

如果镜像没有打包好,就会出现 32G 的空间,实际上只分到 1 GB 的区,用上一段时间,日志就会写满这个分区,然后报错。

这里是一种在 Linux 下通用的,无损拓展分区的方法。

这里的拓展只能将现有分区,拓展到后面跟着的连续分区上。

无法拓展当前正在运行的系统的分区。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 接着上一步,不要重启设备

# 刷新设备
partprobe /dev/mmcblk1

# 找到对应的分区
lsblk
#mmcblk1 179:32 0 28.9G 0 disk
#├─mmcblk1p1 179:33 0 32M 0 part /mnt/mmcblk1p1
#└─mmcblk1p2 179:34 0 1G 0 part

# 最大那个分区一般就是系统分区,索引为 2
# 扩容分区(这个无法在正在运行的系统下执行)
parted /dev/mmcblk1 resizepart 2 100%

# 刷新设备
partprobe /dev/mmcblk1

#mmcblk1 179:32 0 28.9G 0 disk
#├─mmcblk1p1 179:33 0 32M 0 part /mnt/mmcblk1p1
#└─mmcblk1p2 179:34 0 28.8G 0 part /rom

# 拓展文件系统到当前内核上
resize2fs /dev/mmcblk2

# 关机,拔卡,再上电即可
# poweroff -f

参考资料

【1】: https://www.right.com.cn/forum/thread-344825-1-1.html
【2】: https://imgki.com/archives/openwrt-lean.html
【3】: https://www.cnblogs.com/fansys/articles/12142292.html
【4】: https://blog.csdn.net/wxq4100798/article/details/104006964