在Ubuntu-12.04环境下使用新的Rust开发工具

在老旧的系统环境下使用Rust开发工具

笔者的一台硬件资源紧张的旧电脑安装了Ubuntu-12.04,希望在其上运行比较新的Rust开发工具,但却发现其因glibc较老,不能正常运行cargo工具,结果如下:

yejq@UNIX:~$ uname -a
Linux UNIX 3.13.0-32-generic #57~precise1-Ubuntu SMP Tue Jul 15 03:51:20 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
yejq@UNIX:~$ lsb_release -a
No LSB modules are available.
Distributor ID:	Ubuntu
Description:	Ubuntu 12.04.5 LTS
Release:	12.04
Codename:	precise
yejq@UNIX:~$ cargo new --bin hello
cargo: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.17' not found (required by cargo)

如上,cargo可执行文件对glibc最低版本要求是GLIBC_2.17,而Ubuntu-12.04系统的glibc版本较低,因此不能正常运行。一种可行的解决方法是使用docker容量在Ubuntu-12.04系统下使用新的Rust开发工具;但限于笔者对docker了解程度比较浅,并没有尝试该方法。笔者想到的方法也比较简单直接(此前的博客对该方法有相关的说明):在Ubuntu-12.04系统上安装Ubuntu-22.04系统的glibc动态库(不替换原先的glibc库),之后修改Rust开发工具的可执行文件,强制其依赖新的glibc库。

在Ubuntu-22.04下载并解压新的glibc动态库

首先,笔者需要另一台安装了较新版本Ubuntu的系统环境(Ubuntu-22.04),使用apt-get download命令下载四个相关的deb软件包:

yejq@ubuntu:~/x64_libs$ apt-get download libc6
Get:1 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/main amd64 libc6 amd64 2.35-0ubuntu3.6 [3,236 kB]
Fetched 3,236 kB in 1s (2,870 kB/s)
yejq@ubuntu:~/x64_libs$ apt-get download libgcc-s1
Get:1 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/main amd64 libgcc-s1 amd64 12.3.0-1ubuntu1~22.04 [53.9 kB]
Fetched 53.9 kB in 0s (123 kB/s)     
yejq@ubuntu:~/x64_libs$ apt-get download libstdc++6
Get:1 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/main amd64 libstdc++6 amd64 12.3.0-1ubuntu1~22.04 [699 kB]
Fetched 699 kB in 1s (1,158 kB/s)  
yejq@ubuntu:~/x64_libs$ apt-get download zlib1g
Get:1 https://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/main amd64 zlib1g amd64 1:1.2.11.dfsg-2ubuntu9.2 [58.4 kB]
Fetched 58.4 kB in 0s (145 kB/s)  
yejq@ubuntu:~/x64_libs$ ls -lh *.deb
-rw-r--r-- 1 yejq yejq 3.1M Jan 10 20:40 libc6_2.35-0ubuntu3.6_amd64.deb
-rw-r--r-- 1 yejq yejq  53K Jun 29  2023 libgcc-s1_12.3.0-1ubuntu1~22.04_amd64.deb
-rw-r--r-- 1 yejq yejq 683K Jun 29  2023 libstdc++6_12.3.0-1ubuntu1~22.04_amd64.deb
-rw-r--r-- 1 yejq yejq  58K Oct 18  2022 zlib1g_1%3a1.2.11.dfsg-2ubuntu9.2_amd64.deb

之后再手动解压这四个软件包,其中包含了我们要在Ubuntu-12.04系统中安装的动态库。以libgcc-s1软件包为例,下面是解压的操作:

yejq@ubuntu:~/x64_libs$ ls -lh libgcc-s1_12.3.0-1ubuntu1~22.04_amd64.deb
-rw-r--r-- 1 yejq yejq 53K Jun 29  2023 libgcc-s1_12.3.0-1ubuntu1~22.04_amd64.deb
yejq@ubuntu:~/x64_libs$ ar x libgcc-s1_12.3.0-1ubuntu1~22.04_amd64.deb
yejq@ubuntu:~/x64_libs$ ls -lh control.tar.zst data.tar.zst debian-binary
-rw-r--r-- 1 yejq yejq 1.7K Feb 17 20:15 control.tar.zst
-rw-r--r-- 1 yejq yejq  51K Feb 17 20:15 data.tar.zst
-rw-r--r-- 1 yejq yejq    4 Feb 17 20:15 debian-binary
yejq@ubuntu:~/x64_libs$ tar -axf data.tar.zst
yejq@ubuntu:~/x64_libs$ find ./lib
./lib
./lib/x86_64-linux-gnu
./lib/x86_64-linux-gnu/libgcc_s.so.1
yejq@ubuntu:~/x64_libs$ mkdir -p lib64
yejq@ubuntu:~/x64_libs$ mv ./lib/x86_64-linux-gnu/* ./lib64/

如上,使用ar x命令解压deb包可以获得三个文件:control.tar.zst/data.tar.zst/debian-binary;之后再次解压data.tar.zst,可得到./lib文件夹,其中包含了我们想要的动态库。对另外三个deb需要重复这个解压的操作。最后将所有的动态库全部都集中到./lib64文件夹下,复制到Ubuntu-12.04系统中(注意软链接的复制)。笔者得到的lib64文件夹中的内容有(多了一些ncurses的库):

yejq@ubuntu:~/x64_libs$ ls ./lib64
audit                   libmenu.so.6.3      libpthread.so.0
gconv                   libm.so.6           libresolv.so.2
ld-linux-x86-64.so.2    libmvec.so.1        librt.so.1
libanl.so.1             libncurses.so.6     libstdc++.so.6
libBrokenLocale.so.1    libncurses.so.6.3   libstdc++.so.6.0.30
libc_malloc_debug.so.0  libnsl.so.1         libthread_db.so.1
libc.so.6               libnss_compat.so.2  libtic.so.6
libdl.so.2              libnss_dns.so.2     libtic.so.6.3
libform.so.6            libnss_files.so.2   libtinfo.so.6
libform.so.6.3          libnss_hesiod.so.2  libtinfo.so.6.3
libgcc_s.so.1           libpanel.so.6       libutil.so.1
libmemusage.so          libpanel.so.6.3     libz.so.1
libmenu.so.6            libpcprofile.so     libz.so.1.2.11

在Ubuntu-12.04系统上修改新的glibc

笔者在Ubuntu-12.04系统下创建了/home/user/x64_libs文件夹,并将lib64文件夹复制到该目录。之后笔者通过modify.sh脚本,直接修改了lib64中的动态库:

root@UNIX:/home/user/x64_libs# ls
lib64  modify.sh
root@UNIX:/home/user/x64_libs# ./modify.sh
xxd -g 26 -l 26 -s 11712 lib64/gconv/gconv-modules.cache
INFO: processing [lib64/gconv/gconv-modules.cache], (/usr/lib/x86_64-linux-gnu/) replaced 1 time(s).
xxd -g 26 -l 26 -s 180311 lib64/ld-linux-x86-64.so.2
xxd -g 26 -l 26 -s 182135 lib64/ld-linux-x86-64.so.2
INFO: processing [lib64/ld-linux-x86-64.so.2], (/usr/lib/x86_64-linux-gnu/) replaced 2 time(s).
xxd -g 26 -l 26 -s 1951808 lib64/libc.so.6
xxd -g 26 -l 26 -s 1953808 lib64/libc.so.6
INFO: processing [lib64/libc.so.6], (/usr/lib/x86_64-linux-gnu/) replaced 2 time(s).
xxd -g 16 -l 16 -s 188955 lib64/ld-linux-x86-64.so.2
xxd -g 16 -l 16 -s 204139 lib64/ld-linux-x86-64.so.2
INFO: processing [lib64/ld-linux-x86-64.so.2], (/etc/ld.so.cache) replaced 2 time(s).
xxd -g 22 -l 22 -s 180288 lib64/ld-linux-x86-64.so.2
xxd -g 22 -l 22 -s 182112 lib64/ld-linux-x86-64.so.2
INFO: processing [lib64/ld-linux-x86-64.so.2], (/lib/x86_64-linux-gnu/) replaced 2 time(s).
xxd -g 9 -l 9 -s 180344 lib64/ld-linux-x86-64.so.2
xxd -g 9 -l 9 -s 182168 lib64/ld-linux-x86-64.so.2
INFO: processing [lib64/ld-linux-x86-64.so.2], (/usr/lib/) replaced 2 time(s).
xxd -g 5 -l 5 -s 26613 lib64/ld-linux-x86-64.so.2
xxd -g 5 -l 5 -s 44617 lib64/ld-linux-x86-64.so.2
xxd -g 5 -l 5 -s 180338 lib64/ld-linux-x86-64.so.2
xxd -g 5 -l 5 -s 182162 lib64/ld-linux-x86-64.so.2
INFO: processing [lib64/ld-linux-x86-64.so.2], (/lib/) replaced 4 time(s).
xxd -g 27 -l 27 -s 189539 lib64/ld-linux-x86-64.so.2
xxd -g 27 -l 27 -s 205047 lib64/ld-linux-x86-64.so.2
INFO: processing [lib64/ld-linux-x86-64.so.2], (/lib64/ld-linux-x86-64.so.2) replaced 2 time(s).
xxd -g 27 -l 27 -s 1982000 lib64/libc.so.6
INFO: processing [lib64/libc.so.6], (/lib64/ld-linux-x86-64.so.2) replaced 1 time(s).
`/lib64/ld-linux-x86-64.so.y' -> `/home/user/x64_libs/lib64/ld-linux-x86-64.so.2'

脚本modify.sh调用了笔者编写的一个简单的hed工具,用于批量替换二进制文件中的字符串或二进制数据(有需要可以联系笔者),该脚本的内容如下:

root@UNIX:/home/user/x64_libs# cat modify.sh 
#!/bin/bashREPSTR='/home/user/x64_libs/lib64/'
OLDSTR='/usr/lib/x86_64-linux-gnu/'if [ $UID -ne 0 ] ; thenecho "Error, run again as root." 1>&2exit 1
fihed 'lib64/gconv/gconv-modules.cache' \'lib64/ld-linux-x86-64.so.2' \'lib64/libc.so.6' -s \"${OLDSTR}" "${REPSTR}"
sync ; sleep 1# /lib/
# /usr/lib/
# /lib/x86_64-linux-gnu/
hed 'lib64/ld-linux-x86-64.so.2' -s \'/etc/ld.so.cache' \'/etc/ld.so.cachy' \'/lib/x86_64-linux-gnu/' \'/NON/x86_64-linux-gnu/' \'/usr/lib/' \'/usr/NON/' \'/lib/' \'/NON/'sync ; sleep 1
hed 'lib64/ld-linux-x86-64.so.2' \'lib64/libc.so.6' -s \'/lib64/ld-linux-x86-64.so.2' \'/lib64/ld-linux-x86-64.so.y'ln -sv "$(readlink -f ./lib64/ld-linux-x86-64.so.2)" \'/lib64/ld-linux-x86-64.so.y'sync

该操作完成后,接下来就需要修改Rust开发工具了。

修改安装于Ubuntu-12.04系统上的Rust工具链

笔者将Rust开发工具链安装到了/opt/rust-lang路径下(可参考笔者之前的相关博客);实际上,这个工具链是在Ubuntu-22.04下安装的,之后笔者将其打包复制到了Ubuntu-12.04系统中。执行以下命令,可以批量替换/opt/rust-lang路径下的可执行文件使用的动态链接器(从而强制其使用在Ubuntu-22.04系统下载的新的glibc动态库):

root@UNIX:/opt/rust-lang# find ./ -type f -print0 | xargs -0 -i hed {} -s /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.y

以上命令执行完成后,就可以在Ubuntu-12.04系统中正常使用新版本的Rust开发工具了:

yejq@UNIX:~$ cargo --version
cargo 1.72.1 (103a7ff2e 2023-08-15)
yejq@UNIX:~$ cargo new --bin helloCreated binary (application) `hello` package
yejq@UNIX:~$ cd hello/
yejq@UNIX:~/hello$ ls
Cargo.toml  src
yejq@UNIX:~/hello$ cargo build --release -j1Compiling hello v0.1.0 (/home/yejq/hello)Finished release [optimized] target(s) in 1.00s
yejq@UNIX:~/hello$ ./target/release/hello 
Hello, world!

这种方法虽然可行,但仍存在一个问题:Ubuntu-12.04系统安装的gcc版本太老了,它作为Rust在编译构建时的链接器,可能会存在链接失败的问题。不过针对这个潜在的问题,我们仍有解决方案:从此处下载新版本的gcc编译器,通过TARGET_CC这一与Rust编译链接相关的环境变量强制其使用新版本的gcc作为链接器;这里笔者就不展开了。

总结

这种修改、替换应用使用的动态链接器(从而间接指定使用的glibc动态库)的方法,可以方便地为老系统安装一些新的应用。在一些工作环境受限的条件下(如不能安装新的系统作为开发环境),能够让我们不受过多的限制,不影响我们对开发工具的选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/686644.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电商+支付双系统项目------支付系统的构思

本篇文章会讲讲支付的一些相关的名词概念以及怎么去设计支付系统,通过理解支付的这些名词概念和支付系统的架构,为接下来写支付系统的代码做好准备。 目录 支付------支付资质 支付------支付场景 微信 付款码支付 Native支付 支付宝 条码付 扫码…

问卷设计初探:题目类型概览与注意事项梳理

问卷法常被人们应用于社会调查中,它能反馈出最真实的社会信息。所以,很多企业为了最大程度地了解市场,也经常使用问卷调查法进行研究。不过,想要发挥出问卷法的最大用处,前提是要将问卷设计规范并且可量化。 想要设计…

在JavaScript中的防抖函数 - 通过在React中构建自动完成功能来解释

当你将一个新应用推向生产环境时,你希望确保它用户友好。网站的性能是用户体验的关键部分。每个用户都希望网站及其内容能够快速加载。每一秒都是宝贵的,可能导致用户再也不会访问你的网站。 在本指南中,我们将了解JavaScript中一个非常重要…

SQL 精讲-MySql 常用函数,MySQL语句精讲和举例

FORMAT(数值,保留位数) 四舍五入 SELECT *,FORMAT(score/3,2) from studentROUND(数值,保留位数) 四舍五入 SELECT ROUND(score/3,2) from studentCONCAT(字符串 1,字符串 2) 字符串拼接 SELECT CONCAT(customer_name, (,address,)) from mt_customerLEFT(字符串,长度) 截取…

内存处理函数 内存池

内存处理函数 内存申请函数(stdlib.h) malloc 原形:void *malloc(size_t size); 功能:用于动态分配指定大小的内存块,分配的内存块不会被初始化,内容是未定义的。 返回值:若分配成功,返回一个指向该内存块…

同步缓冲器设计(Synchronous FIFO)

缓冲器又称为队列,是一种数据暂存的机制。缓冲器存在的必要是因为当数据传出端传出数据时,接收端不一定能实时地接收,如果接收端不能实时地接收,又无缓冲器的存在,数据将不可避免会遗失。如果输出输入端的时钟频率一致…

2024.2.15 模拟实现 RabbitMQ —— 消息持久化

目录 引言 约定存储方式 消息序列化 重点理解 针对 MessageFileManager 单元测试 小结 统一硬盘操作​​​​​​​ 引言 问题: 关于 Message(消息)为啥在硬盘上存储? 回答: 消息操作并不涉及到复杂的增删查改消…

人工智能学习与实训笔记(十四):Langchain之Agent

人工智能专栏文章汇总:人工智能学习专栏文章汇总-CSDN博客 本篇目录 0、概要 1、Agent整体架构 2、langchain中agent实现 3、Agent业务实现逻辑 0、概要 Agent是干什么的? Agent的核心思想是使用语言模型(LLM)作为推理的大脑…

redis为什么使用跳跃表而不是树

Redis中支持五种数据类型中有序集合Sorted Set的底层数据结构使用的跳跃表,为何不使用其他的如平衡二叉树、b树等数据结构呢? 1,redis的设计目标、性能需求: redis是高性能的非关系型(NoSQL)内存键值数据…

SpringBoot中公共字段的自动填充

目录 1 前言 2 使用方法 2.1 自定义枚举类 2.2 自定义注解AutoFill 2.3 自定义切面类并设定切入点 2.4 切面类中设置前置通知,对公共字段赋值 2.5 在方法上添加自定义注解 3 最后 1 前言 在我们的项目中,项目表可能会有一些公共的字段需要我们的…

【51单片机实验笔记】开关篇(二) 矩阵按键

目录 前言原理图分析矩阵按键扫描算法 软件实现1. 矩阵键盘检测2. 简易计算器实现 总结 前言 本节内容,我们学习一下矩阵按键,它是独立按键的阵列形式,常见的应用即键盘。 本节涉及到的封装源文件可在《模块功能封装汇总》中找到。 本节完…

websocket数据帧格式

客户端、服务端数据的交换,离不开数据帧格式的定义。因此,在实际讲解数据交换之前,我们先来看下WebSocket的数据帧格式。 WebSocket客户端、服务端通信的最小单位是帧(frame),由1个或多个帧组成一条完整的消…

基于协同过滤的时尚穿搭推荐系统

项目:基于协同过滤的时尚穿搭推荐系统 摘 要 基于协同过滤的时尚穿搭推荐系统是一种能自动从网络上收集信息的工具,可根据用户的需求定向采集特定数据信息的工具,本项目通过研究服饰流行的分析和预测的分析和预测信息可视化时尚穿搭推荐系统…

2月12作业

1.会出现段错误,因为p申请的堆区内存未返回给str,导致str仍然指向NULL,无法将"hello world"拷贝给str 2.会出现段错误,因为p是一个局部变量,函数结束时,p将被释放,不能返回它的地址 …

C++中的volatile:穿越编译器的屏障

C中的volatile:穿越编译器的屏障 在C编程中,我们经常会遇到需要与硬件交互或多线程环境下访问共享数据的情况。为了确保程序的正确性和可预测性,C提供了关键字volatile来修饰变量。本文将深入解析C中的volatile关键字,介绍其作用、…

浅谈电商场景中的扣除库存问题

库存 一、场景二、扣减时机1.下单时扣库存2.支付完成扣库存3.预扣除 三、库存存储方案1.数据库存储2.数据库缓存混合存储 四、整体方案1.单数据库方案2.主从数据库方案3.主从数据库缓存方案4.数据库缓存混合存储 五、其他情况1.秒杀QPS过高2.Redis QPS过高3.Master DB QPS过高4…

使用ShardingJDBC实现分库分表

一、测试环境 JDK&#xff1a;1.8SpringBoot&#xff1a;2.7.17MySQL驱动&#xff1a;5.1.49MyBatis&#xff1a;2.3.1shardingJDBC&#xff1a;5.1.0 二、核心依赖 <!-- mysql 驱动 --> <dependency><groupId>mysql</groupId><artifactId>mysq…

网站架构演变、LNP+Mariadb数据库分离、Web服务器集群、Keepalived高可用

目录 day02 深入理解程序的数据存储 验证 配置NFS服务器 配置代理服务器 配置名称解析 day02 深入理解程序的数据存储 程序将文字数据保存到数据库中程序将非文字数据&#xff08;如图片、视频、压缩包等&#xff09;保存到相应的文件目录中 验证 发一篇文章&#xf…

Manifest merger failed with multiple errors, see logs

问题 Manifest merger failed with multiple errors, see logs详细问题 笔者进行Android 项目开发&#xff0c;修改AndroidManifest.xml代码后&#xff0c;控制台报错 AndroidManifest.xml报错核心代码 <manifest><uses-permission android:name"android.perm…

StringBuilder/StringBuffer类(Java)

StringBuilder/StringBuffer类 当对字符串进行修改的时候&#xff0c;使用 StringBuffer / StringBuilder 类更方便。和 String 类不同的是&#xff0c;StringBuffer 和 StringBuilder 类的对象能够被多次的修改&#xff0c;并且不产生新的未使用对象。方法类似 public class…