#Bug

以前对软件包的构建不太了解,喜欢随意修改软件源列表,软件源和当前系统的版本不一致就会出现安装了一个依赖较多的软件包后会出现连锁反应,修改了所有依赖的软件包版本,导致系统故障。最常出现的就是修改了GCC版本,导致GLIBCXX版本不一致,导致系统软件无法运行。

如果你的系统还能正常安装软件,那么修改软件源和当前系统版本保存一致,然后更新软件,并重新安装GCC即可解决问题。具体步骤如下:

# 修改软件源
sudo vim /etc/apt/sources.list
# 检查当前系统版本
lsb_release -a
# 将软件源修改为当前系统版本的软件源,Ubuntu系统版本号对应的软件源列表可以在https://wiki.ubuntu.com/Releases查看
# 更新软件
sudo apt update
# 安装GCC,build-essential包含了GCC
sudo apt install build-essential

如果你和我一样倒霉,连 apt 都无法使用,那么可以使用 dpkg 命令手动安装 GCC。

因为误操作在 Ubuntu 20.04 上安装了 Ubuntu 18.04 的 GCC,导致系统软件无法运行,apt 也无法使用,所以只能手动安装 GCC。

apt: libx86_64-linux-gnu-libstdc++.so.6: version `GLIBCXX_3.4.29' not found (required by libx86_64-linux-gnulibapt-private.so.0.0)

既然libstdc++版本不一致,我们就去下载对应版本的GCC,访问https://packages.ubuntu.com/,在下方的搜索框中输入libstdc++6,选择对应的系统版本,然后下载对应的GCC。

点击搜索结果,点击系统的架构,一般为amd64,

具体下载地址比较隐蔽,直接点击红框的链接没有反应,你可以右键另存为到本地,我习惯复制链接后用wget下载。

下载完成后,使用dpkg命令安装GCC。

sudo dpkg -i libstdc++6_12.3.0-1ubuntu1\~22.04_amd64.deb

之后可以检查一下缺失的GLIBCXX版本已经安装。

$ strings /lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX                               
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19
GLIBCXX_3.4.20
GLIBCXX_3.4.21
GLIBCXX_3.4.22
GLIBCXX_3.4.23
GLIBCXX_3.4.24
GLIBCXX_3.4.25
GLIBCXX_3.4.26
GLIBCXX_3.4.27
GLIBCXX_3.4.28
GLIBCXX_3.4.29
GLIBCXX_3.4.30
GLIBCXX_DEBUG_MESSAGE_LENGTH

此时apt 应该就可以正常使用了,我们只需要修复一下所有软件包,让它回到正确的版本即可恢复系统。

sudo apt --fix-broken install

解决方案

VirtualBox Ubuntu 无法联网,重启后可以联网但是几分钟后断开网络。笔者的情况是因为 NetworkManager 自动修改了网络配置导致无法联网,具体现象是开机后网卡信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
user@allone:~$ ifconfig
brq64ff9b38-fa: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether ce:29:de:12:35:06 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255
inet6 fe80::2e8f:2be6:3752:dec4 prefixlen 64 scopeid 0x20<link>
ether 08:00:27:18:31:21 txqueuelen 1000 (Ethernet)
RX packets 947 bytes 584483 (584.4 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 800 bytes 116611 (116.6 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

此时网络可以正常使用,经过一两分钟后网络信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
user@allone:~$ ifconfig
brq64ff9b38-fa: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.2.15 netmask 255.255.255.0 broadcast 10.0.2.255
ether ce:29:de:12:35:06 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::2e8f:2be6:3752:dec4 prefixlen 64 scopeid 0x20<link>
ether 08:00:27:18:31:21 txqueuelen 1000 (Ethernet)
RX packets 947 bytes 584483 (584.4 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 800 bytes 116611 (116.6 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0


也就是默认虚拟网卡的 IP 地址丢失,而不知名网卡 brq64ff9b38-fa 却拥有了 IP,此时网络不可用。如果有类似情况,可以使用以下方式尝试解决,如果是其他问题。请酌情参考。

  1. 关闭 NetworkManager
1
2
sudo systemctl stop NetworkManager

1
sudo systemctl disable NetworkManager
1
sudo systemctl mask NetworkManager
  1. 开启 systemd-networkd
1
sudo systemctl unmask systemd-networkd.service
1
2

sudo systemctl enable systemd-networkd.service
1
2

sudo systemctl start systemd-networkd.service
  1. 配置 Netplan

编辑/etc/netplan/01-network-manager-all.yaml

1
2
3
4
5
6
7
8
9
10
11
network:
version: 2
renderer: networkd
ethernets:
enp0s3:
dhcp4: yes
dhcp6: yes
addresses: [10.0.2.15/23]
nameservers:
addresses: [8.8.8.8, 8.8.4.4]
optional: true

其中 enp0s3 为网卡名称,addresses 为网卡对应的 IP,均可以通过 ifconfig 查询。

以下是一些背景知识,以及问题回溯有兴趣可以继续阅读。

背景知识

NetworkManager 与 systemd-networked

NetworkManager 是一项后端服务,用于控制 Ubuntu 操作系统上的网络接口。NetworkManager 的替代方法是 systemd-networked,这两者只能使用一个。在 Ubuntu 桌面上,NetworkManager 是通过图形用户界面管理网络界面的默认服务。因此,如果要通过 GUI 配置 IP 地址,则应启用 NetworkManager。如果用的是无桌面的 Server 版,就可以使用 systemd-networked 来管理网络。

这两种方式都可以通过配置 netplan,即/etc/netplan/01-network-manager-all.yaml 来管理网络,但是在 renderer 属性中配置有所不同,使用 NetworkManager 时配置如下:

1
2
3
network:
version: 2
renderer: NetworkManager

而使用 systemd-networked 时,配置如下:

1
2
3
network:
version: 2
renderer: networkd

有时无法联网可能是因为配置与实际使用的网络管理方式不匹配导致的。

保留现场

使用 VSCode 远程登录失败,报错:Failed to connect to the remote extension host server (Error: WebSocket close with status code 1006)。

解决方法

1
2
3
4
5
6
7
8
9
10
11
vim /etc/ssh/sshd_config

AllowTcpForwarding no

AllowAgentForwarding no

# 替换为

AllowTcpForwarding yes

AllowAgentForwarding yes

保存后重启 sshd 服务:

1
systemctl restart sshd

保留现场

1
2
3
ImportError: No module named 'ConfigParser'

Command "python setup.py egg_info" failed with error code 1 in

解决方法

在 Python 3.x 版本后,ConfigParser.py 已经更名为 configparser.py 所以出错!

可以切换 Python2 执行。

也可以尝试将文件重命名为ConfigParser.py

以下为参考,每个人安装路径可能不一样,可以全局搜索configparser.py

1
cp /usr/lib/python3.7/configparser.py /usr/lib/python3.7/ConfigParser.py

保留现场

在 LaTeX 编译中报错:Missing character: There is no (U+00A0) (U+00A0) in font JetBrains Mono。

探究原因

如果要搞清楚具体原因,就得从字符与字符编码说起了。解决办法直接跳到下一节吧。

字符,就是“a”,“A”,“你”等书写符号。

字符集,通常就是某种语言字符集合,比如英语就是ASCII 字符集,中文有GBK 字符集

注意,不是每种语言只对应一种字符集(比如 GB2312,GBK,GB18030 都包含了常用汉字,后者是前者的超集),而且字符集也不是只对应一种语言,例如 Unicode 字符集就包含所有语言字符,字符集只是设计者为了给字符编码(Code Point/Numbering)设计编码时,为了收录到命名的字符集合,但是通常设计者都为字符集设计了对应的编码规范。

字符编码,给字符集里的字符编号。

编码页,在 unicode 发明之前,各个地区都用 2 字节编码自己的字符集,相同的编码对应不同的字符,为了本地化,Windows 发明了编码页,来对应不同的字符集。

字符编码,对给定的字符编码编码成字节表示。

早期,字符被编号后,存储时就按照编号的方式存储,没有 encoding 的过程,后来发明 Unicode 后,发现如果按照 Unicode 的编号直接存储的话,对于英文字符就有很大存储浪费,因为任意字符都需要 2 字节存储,后来人们发明 UTF-8 这种编码方式,这样 UTF-8 就可以一个字节表示英文字符,2 个以上字节表示汉字字符。

字体,定义了字符的图形表示,现在的软件展示字符时用 Unicode 表示,字体是 Unicode 编码和字符图形的映射,而以往比如 WindowsCMD 控制台,没有对应 Unicode,则用编码页来区分,所以字体就是字符编码金和代码页到字符图形的映射。

文本文件存储在磁盘上,都是一系列的字节流,如果不告诉文本编辑器该文件的编码方式,编辑器会尝试用默认的编码(依赖于操作系统设置)又或者自己探测(detect,比如文件开头有 FFEF 或者 EFFF 字节就表明 UTF-16 编码,有很多 10,110 开头的字节,很可能是 UTF-8 编码)并尝试解码,如果没有猜对,那就会显示乱码

回到出错的问题,提示我们在字体 JetBrains Mono中没有U+00A0,我们搜索一下就知道这是一个 Unicode 字符NO-BREAK SPACE。我们通过上面的了解也知道了,字体就是字符编码到字符图像的映射,但是一个字体尤其是一些有专门用途的字体(比如 JetBrains Mono 设计初衷是为软件工程显示代码用的),它不会映射所有的字符,JetBrains Mono 这个字体里就没有映射 U+00A0。这就导致在 LaTeX 编译时无法在字体中找到对应的字符图像显示

所有解决办法就是要不替换掉这个字符,要不换个字体。

解决方法

VSCode 正则搜索\U00A0即可搜索到相关字符,将其替换成空格。

参考

字符,字符集,字符编码,编码页,字体 - 简书

保留现场

1
Unable to load picture or PDF file 'xxxxxx' <to be read again> xxxx

探究原因

图片链接错误,转换 PDF 过程中会先下载所有图片到AppData/Local/Temp/tex2pdf.****文件夹里,因为无法正常下载图片,所有报错。检查图片链接是否有效。

解决方法

检查图片链接是否有效。

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×