64 位 Linux 系统安装与清理 32 位环境

2023-07-26 ⏳2.8分钟(1.1千字)

我之前 200 块收了一台华硕 RT-AC1900P 无线路由器,刷了梅林系统,用作家庭网关。这货用的是 2.6.36.4brcmarm 内核。因为是十多年前的内核,WireGuard 模块是不用想了,但还可以编译像 IPIP/GRE 等隧道模块,具体编译过程我后面会撰文介绍。博通 (Broadcom) 只有 32 位工具链,而我的服务器是 64 位 Ubuntu,无法直接运行。今天就分享怎样在 64 位 Linux 系统上安装和清理 32 位运行环境。

在纯 64 位 Linux 环境运行 32 位程序可能会报错:

$ ./arm-none-eabi-gcc --version
-bash: ./arm-none-eabi-gcc: No such file or directory

明明可执行文件就在那里,但 bash 还是报文件不存。查看文件信息确认是 32 位程序:

$ file ./arm-none-eabi-gcc
./arm-none-eabi-gcc: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-l
inux.so.2, for GNU/Linux 2.6.8, stripped

那为什么说是可能会报错?大家可以试试,如果是 Go 语言编译出来的 32 位程序,大概率会正常运行。这里的区别是 Go 程序默认是静态链接,不依赖系统上安装的动态链接库1。而 64 位 CPU 本身就支持运行 32 位指令,所以 Go 程序大多可以直接运行。

查看 Go 程序信息:

$ file led
led: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, Go BuildID=lyyBrECmPyAxisV7K8CW/4BUObJmofsE9O5rEljuA/KDrmeLORek8eFaiXW8ov/s4oxB_6x564bJCZyGtO6, with debug_info, not stripped

这里的 statically linked 表示静态链接。静态链接不依赖系统上的 so 文件。

所以说所谓的 32 位运行环境就是一组相关的动态链接库,确保 32 位程序在运行时能正常加载对应的 so 文件。我们要做的就是怎么安装对应的库文件。

首先开启 32 位架构,也就是 i386 架构:

$ sudo dpkg --add-architecture i386

然后安装 i386 架构核心动态库:

$ sudo apt-get install gcc-multilib g++-multilib

剩下就是根据具体的程序安装对应的依赖库。库分两种,一种是名字里有 32 字样,比如 lib32stdc++6,还有一种是要在库名面指定架构,比如 libelf1:i386。缺啥补啥就行。

然后就能正常运行了。不过我的 VPS 硬盘太小,只有 20G,根本不够用,就只能转用朋友的机器。但我也是一个有强迫症的人,不用的包必须清理,别无选择。

如果我们直接删除 i386 架构,系统会报错:

dpkg --remove-architecture i386
dpkg: error: cannot remove architecture 'i386' currently in use by the database

显然是因为系统里已经安装了 32 位包。我们可以通过 dpkg 配合 grep 找到它们。

dpkg -l | grep :i386

当然也可以使用 dpkg 内置的命令 dpkg -l "*:i386",但我觉得配合 grep 更灵活,也更通用。

然后可以使用 awk {print $2} 提取包名,也就是第二列,最后使用 xargs 配合 aptitude 批量删除:

dpkg -l | grep :i386 | awk {print $2} | xargs aptitude purge -y

这里最后的 -y 选项是告诉 aptitude 直接删除,不要再要求用户确认。不过考虑到上一次的惊险体验2,我采取了更保守的方案。我先把要删除的包变成一行并用空格分割:

dpkg -l | grep :i386 | awk {print $2} | xargs echo

最后的 xargs echo 就能实现这个效果。然后手工运行 aptitude 看看有什么提示:

sudo aptitude purge gcc-12-base:i386 libc6:i386 libc6-i386 libcom-err2:i386 libcrypt1:i386 libgcc-
s1:i386 libgmp-dev:i386 libgmp10:i386 libgmpxx4ldbl:i386 libgpm2:i386 libgssapi-krb5-2:i386 libidn2-0:i386 libk5crypto3:
i386 libkeyutils1:i386 libkrb5-3:i386 libkrb5support0:i386 libmpc-dev:i386 libmpc3:i386 libmpfr-dev:i386 libmpfr6:i386 l
ibncurses5:i386 libnsl2:i386 libnss-nis:i386 libnss-nisplus:i386 libssl3:i386 libstdc++6:i386 libtinfo5:i386 libtirpc3:i
386 libunistring2:i386
The following packages will be REMOVED:
  gcc-12-base:i386{p} libc6:i386{p} libc6-i386{p} libcom-err2:i386{p} libcrypt1:i386{p} libgcc-s1:i386{p}
  libgmp-dev:i386{p} libgmp10:i386{p} libgmpxx4ldbl:i386{pu} libgpm2:i386{p} libgssapi-krb5-2:i386{p}
  libidn2-0:i386{p} libk5crypto3:i386{p} libkeyutils1:i386{p} libkrb5-3:i386{p} libkrb5support0:i386{p}
  libmpc-dev:i386{p} libmpc3:i386{p} libmpfr-dev:i386{pu} libmpfr6:i386{pu} libncurses5:i386{p} libnsl2:i386{p}
  libnss-nis:i386{pu} libnss-nisplus:i386{pu} libssl3:i386{p} libstdc++6:i386{p} libtinfo5:i386{pu}
  libtirpc3:i386{p} libunistring2:i386{p}
0 packages upgraded, 0 newly installed, 29 to remove and 0 not upgraded.
Need to get 0 B of archives. After unpacking 35.5 MB will be freed.
Do you want to continue? [Y/n/?]

系统会找到其他有依赖的包一并删除,这一步需要用户确认。我看了要删的包,感觉没问题,按 Y 继续。没想到系统显示新的提示:

The following ESSENTIAL packages will be REMOVED!
  libcrypt1:i386

WARNING: Performing this action will probably cause your system to break!
         Do NOT continue unless you know EXACTLY what you are doing!
To continue, type the phrase "I am aware that this is a very bad idea":

说是 libcrypt1:i386 是核心包,删除它可能会破坏系统。我就有点慌了。别跟上次那样把系统搞坏了。但讲道理 libcrypt1:i386 应该只有 32 位程序在用,系统不会用,SSH 等程序也是 64 位的,应该也不依赖。不妨检查一下 SSH 依赖的版本:

$ ldd /usr/sbin/sshd|grep crypt
        libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3 (0x00007effdb000000)
        libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007effdb532000)
        libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007effdaac2000)
        libk5crypto.so.3 => /lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007effda9fc000)

从路径 /lib/x86_64-linux-gnu 就能看出依赖的是 64 位版的。我们用 dpkg -L libcrypt1:i386 查看包内文件:

/lib/i386-linux-gnu/libcrypt.so.1
/lib/i386-linux-gnu/libcrypt.so.1.1.0
/usr/share/doc/libcrypt1/changelog.Debian.gz
/usr/share/doc/libcrypt1/copyright

路径是 /lib/i386-linux-gnu,所以不会影响 SSH 等 64 位程序,可以删!

删除它得用 dpkg 的 --force-remove-protected 参数:

$ sudo dpkg --purge --force-remove-protected libcrypt1:i386 ...

删完之后就可以清理 i386 架构了:

$ sudo dpkg --add-architecture i386

最后重启系统,还能正常登录,万幸,哈哈~以上就是本文的全部内容。大家如果有关于 Linux 系统的问题也可以给我留言。


  1. 也就是 /usr/lib 目录下的一众 *.so 文件。↩︎

  2. 参见我的另一篇文章 ./vps-rebirth.html↩︎