我安装了 64 位(amd64 又名 x86_64)Debian 或 Ubuntu。我偶尔需要运行32位(i386/i686)程序,或者为32位系统编译程序。我怎样才能以最少的麻烦做到这一点?
额外奖励:如果我想使用旧版本或新版本的发行版来运行或测试怎么办?
答案1
对于当前版本
当前的 Debian 和 Ubuntu 具有多架构支持:您可以以简单的方式在同一系统上混合 x86_32 (i386) 和 x86_64 (amd64) 软件包。这称为多架构支持 - 请参阅乌班图或者德班维基更多信息。
看沃克的回答以获得简单、最新的答案。
对于旧版本
在旧版本中,Debian 和 Ubuntu 在 amd64 上附带了许多 32 位库。安装ia32-libs
软件包具有一组基本的 32 位库,以及可能依赖于该库的其他软件包。如果您拥有所有必需的库,您的 32 位可执行文件应该可以运行。对于开发,安装gcc-multilib
,以及可能依赖它的其他软件包,例如g++-multilib
.你可能会发现binutils-multiarch
也有用,并且ia32-libs-dev
在 Debian 上。将选项传递-m32
给 gcc 以针对 ix86 进行编译。
请注意,无论您安装了哪些 32 位用户模式组件,uname -m
仍然会显示x64_64
您是否运行 64 位内核。下面描述的 Schroot 会处理这个问题。
施鲁特
本节是在另一个 Linux 发行版“内部”安装类似 Debian 的发行版的指南。它的措辞是在 64 位 Ubuntu 中安装 32 位 Ubuntu,但应该稍作修改即可适用于其他情况,例如在 Debian stable 中安装 Debian不稳定版,反之亦然。
介绍
这个想法是在子树中安装备用发行版并从中运行。您可以通过这种方式在 64 位系统上安装 32 位系统,或者安装不同版本的发行版,或者安装不同软件包集的测试环境。
这chroot
命令和系统调用启动一个进程,该进程具有仅限于目录树子树的文件系统视图。 Debian 和 Ubuntu 发布施鲁特,一个围绕此功能创建更可用的子环境的实用程序。
安装schroot
包裹 (德班)和debootstrap
包裹 (德班)。 Debootstrap 仅在安装备用发行版时需要,之后可以删除。
设置施根
此示例介绍如何设置 32 位 Ubuntu 10.04LTS (lucid lynx) 备用环境。类似的设置应该适用于 Debian 和 Ubuntu 的其他版本。创建一个/etc/schroot/chroot.d/lucid32
包含以下内容的文件:
[lucid32]
description=Ubuntu 10.04LTS 32-bit
directory=/32
type=directory
personality=linux32
users=yourusername
groups=users,admin
该行directory=/32
告诉 schroot 我们将把 32 位安装的文件放在哪里。该行username=yourusername
表示用户yourusername
将被允许使用 schroot。该行groups=users,admin
表示任一组中的用户都将被允许使用 schroot;你也可以放置一个users=…
指令。
安装新发行版
创建目录并开始使用 debootstrap 填充它。 Debootstrap 为指定的发行版和体系结构下载并安装一组核心软件包。
mkdir /32
debootstrap --arch i386 lucid /32 http://archive.ubuntu.com/ubuntu
你几乎已经有了一个可以运行的系统了;接下来是一些小的改进。当您运行Schroot 时,它会自动覆盖几个文件/32/etc
,特别是 DNS 配置/etc/resolv.conf
和用户数据库/etc/passwd
以及其他文件(这可以被覆盖,请参阅文档)。您可能还需要一劳永逸地手动复制一些文件:
cp -p /etc/apt/apt.conf /32/etc/apt/ # for proxy settings
cp -p /etc/apt/sources.list /32/etc/apt/ # for universe, security, etc
cp -p /etc/environment /32/etc/ # for proxy and locale settings
cp -p /etc/sudoers /32/etc/ # for custom sudo settings
chroot 中不会有文件/etc/mtab
。/etc/fstab
我不建议mount
在 chroot 中手动使用该命令,而是从外部执行。但一定要创建一个足够好的/etc/mtab
命令来使命令df
合理地工作。
ln -s /proc/mounts /32/etc/mtab
使用directory
类型,schroot 将执行绑定安装多个目录,即这些目录将与父安装共享:/proc
, /dev
, /home
, /tmp
。
chroot 中的服务
如此处所述,schroot 不适合运行守护程序。当您退出 schroot 时,schroot 中的程序将被终止。如果您希望它更持久,请使用“普通”schroot 而不是“目录”schroot,并在/etc/fstab
父安装中设置永久绑定安装。
在 Debian 和 Ubuntu 上,服务在安装时自动启动。为了避免这种情况(这可能会破坏 chroot 之外运行的服务,特别是因为网络端口是共享的),请建立一个政策不在 chroot 中运行服务。将以下脚本设置为/32/usr/sbin/policy-rc.d
并使其可执行(chmod a+rx /32/usr/sbin/policy-rc.d
)。
#!/bin/sh
## Don't start any service if running in a chroot.
## See /usr/share/doc/sysv-rc/README.policy-rc.d.gz
if [ "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" ]; then
exit 101
fi
填充新系统
现在我们可以开始使用 chroot。此时您需要安装更多软件包。
schroot -c lucid32
sudo apt-get update
apt-get install lsb-core nano
...
您可能需要生成一些语言环境,例如
locale-gen en_US en_US.utf8
如果 schroot 适用于较旧版本的 Ubuntu,例如 8.04 (hardy),请注意软件包 ubuntu-standard 会引入 MTA。选择nullmailer
而不是默认值postfix
(您可能希望您的 chroot 发送邮件,但您绝对不希望它接收任何邮件)。
更进一步
欲了解更多信息,请参阅schroot
手动的, 这施鲁特常见问题解答和
schroot.conf
手动的。施鲁特是Debian 自动构建器 (buildd) 项目。可能还有其他有用的提示关于 debootstrap 的 Ubuntu 社区页面。
虚拟机
答案2
自从乌班图11.04(自然)和德班7.0(喘息)推出多架构支持,32位和64位库可以在一个系统上共存。要安装 32 位库 libXX,首先将必要的 32 位架构添加到您的系统中:
sudo dpkg --add-architecture i386
sudo apt-get update
然后安装32位库:
sudo apt-get install libXX:i386
ia32-libs 包。从 Ubuntu 12.04 开始,它不再包含任何库,它只引入libXX:i386
包作为依赖项。
编译部分对于C和C++程序来说相当容易,添加-m32
到CFLAG
or CXXFLAG
,这将使生成的程序32位,例如
export CFLAGS="-m32"
gcc main.c -o main
这也适用于基于 makefile 的项目。
答案3
如果您只有 32 位二进制文件,并且想在现代 64 位 Debian/Ubuntu 系统上运行,请执行以下操作:
dpkg --add-architecture i386
apt update
apt install libc6-i386
这已经在 Debian 9 上进行了测试。
答案4
我将其作为 Docker 解决方案撰写 -https://bbosmith.medium.com/running-32-bit-i386-applications-on-64-bit-arm-using-docker-de7a198914a2。 Docker 在任何运行此解决方案的地方都可以工作 - 只需更改设置以适应。
我有一个在任何具有可用 Docker 映像的平台上运行 32 位应用程序的答案。抱歉,这个答案不包括编译。但它对于运行其他平台的二进制文件来说是如此简单和强大,因此它确实值得发布。
假设您想date
从 64 位实例上的 32 位 Debian 实例运行。显然这是人为的 - 插入您选择的二进制文件。
首先证明有一个支持 32 位 Linux 的平台可用:
host $ docker buildx imagetools inspect debian
Name: docker.io/library/debian:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest: sha256:e97ee92bf1e11a2de654e9f3da827d8dce32b54e0490ac83bfc65c8706568116
Manifests:
Name: docker.io/library/debian:latest@sha256:c2cedd7f80a4dd0f9f80d3699bd433ccf3de33ab63bfa2d4c4ba870c998222d6
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/amd64
Name: docker.io/library/debian:latest@sha256:e2e12679dbb45a942e627756196cc8a87182c5de53000b021a051733422e1d45
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm/v5
Name: docker.io/library/debian:latest@sha256:2acb8966cd93f0928d5ed57116849afae60eb8603797ca9b34801620d35236d9
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm/v7
Name: docker.io/library/debian:latest@sha256:6496a3400e12fbff53da7318b304405a5cb2f185a74bdb4458dcc4b645839380
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm64/v8
Name: docker.io/library/debian:latest@sha256:0877f432f15595d9754cdd7c01e8afd53767db4b515b9a47d3e67e1e2f40f520
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/386
Name: docker.io/library/debian:latest@sha256:f464ff1c8422dce7ce2f9c179b7e39a680748b4d0e3e074ad705cf84d4372a0c
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/mips64le
Name: docker.io/library/debian:latest@sha256:5105fb4c3f037b0a6278c3ae1f0320ff1e169a3d7cfb0ca7a7b51f8657039c21
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/ppc64le
Name: docker.io/library/debian:latest@sha256:c5bfba100bac4c910c69710efe8a07b4b39d547f3c75722944eb741845742936
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/s390x
是的! Platform: linux/386
。
如果没有,您需要尝试其他映像而不是 Debian(在本例中使用)或进行一些鸭鸭搜索。
接下来编写一个Dockerfile:
FROM debian
ENTRYPOINT ["date"]
ENTRYPOINT 的形式exec
允许传递参数,例如"+DATE: %D%nTIME: %T"
看https://docs.docker.com/reference/dockerfile/#shell-and-exec-form
构建它:
host $ docker buildx build --platform <target for build> -t <dockeruser>/<dockerImageToBuild>:latest \
--push .
例如。
host $ docker buildx build --platform linux/386 -t bbos/dateegforso:latest --push .
标签名称 ( bbos/dateegforso
) 必须全部小写。
这会将构建映像推送到 Bob 的 docker.io 存储库。推送不是必需的,但会在全局范围内保留图像。
您需要先登录才能启用此推送。
docker login
使用以下命令运行:
docker run --init --platform <platform to run if multiple> <dockeruser>/<dockerImageToBuild>:latest <args>
例如。
docker run --init --platform linux/386 bbos/dateegforso:latest "+DATE: %D%nTIME: %T"
(该图像当前存在,并且该命令应该按原样工作)。
--init
不是必需的,但是如果您有一个长时间运行的任务(显然不是date
)并且您需要终止它,那么您将需要它。否则ctrl-c
将其发送到啦啦之地。
你可以在任何 docker 运行的地方运行这个。 x64 Linux、AMD、AARM64、..