13. 软件包详解,rpm包的查找,安装,升级,卸载,验证等所有操作

本小节会详细介绍linux中的软件包管理,涉及软件包的定义/安装/卸载/依赖等操作。以及会详细演示rpm这个非常重要命令的使用。


前言

本小节会详细介绍linux中的软件包管理,涉及软件包的定义/安装/卸载/依赖等操作。以及会详细演示rpm这个非常重要命令的使用。


软件包

源码包

源码包是一大堆源代码程序,是由程序员按照特定的格式和语法编写出来的。计算机只能识别机器语言,也就是二进制语言,所以源码包的安装需要通过编译器将程序代码翻译成二进制语言,这个过程叫做编译。

源码包的安装需要把源代码编译为二进制代码,安装时间通常都很长。安装25M左右的源码包,可能需要半小时间到一时间。但常见的二进制包安装,例如微信,几百M的文件,也只需要几分钟。

另外源码包的安装需要人为编译,这个过程很容易报错,可能还需要熟悉程序语言进行排错。

为了解决源码安装的这些问题,在linux中更常见的还是使用二进制包进行安装。

二进制包

源码包成功之后产生的包就是二进制包。二进制包在发布之前就已经完成编译工作,因此用户安装的速度会快很多,且安装报错的几率减小。

目前主流的二进制包管理系统有两大类:
RPM 包管理系统:功能强大,安装、升级、査询和卸载简单方便,很多 Linux 发行版使用的软件安装管理方式,例如 红帽、CentOS、SuSE 等。
DPKG 包管理系统:由 Debian Linux 开发的包管理机制,主要应用在 Debian 和 Ubuntu 系统。
RPM 包管理系统和 DPKG 包管理系统原理大同小异,这一系列课程是在Centos7中做实验,所以以RPM包管理系统为主。

源码包 VS二进制包

源码包一般包含多个文件,为了方便发布,通常会将源码包做打包压缩处理,Linux 中最常用的打包压缩格式为“tar.gz”,因此源码包又被称为 Tarball。
源码包通常包含以下内容:
源代码文件。
配置和检测程序(如 configure 或 config 等)。
软件安装说明和软件说明(如 INSTALL 或 README)。

源码包安装软件的好处:
开源,可以修改源代码。
可自由选择所需的功能。
软件是编译安装,安装完成后更加匹配操作系统。
卸载方便。

源码包安装软件的缺点:
安装时候,参数配置和步骤较多,语法容易写错
编译安装时间比二进制安装要长很多。
编译安装过程容易出错,并且一旦出错,很难解决

二进制(rpm)包安装的优点
rpm管理系统简单,通过常见的命令可实现包的安装、升级、査询和卸载。
安装速度比源码包安装快得多。相比源码包,二进制包是在软件发布时已经进行过编译的软件包,所以安装速度比源码包快得多。

二进制(rpm)包安装的缺点
不能看到源代码。
功能选择不灵活。

依赖性

依赖性。有时在安装软件包 x 时需要先安装 y 和 z,而在安装 z 时需要先安装 a 和 b。这就需要先安装 a 和 b,再安装 y 和 z,最后才能安装 x。安装软件包需要有一定的顺序,但是有时依赖性会非常复杂。

软件包的依赖性 在包的安装和卸载过程中需要重点关注,包之间的依赖关系大致可分为以下 2 种:
树形依赖(A-B-C-D):要想安装软件 A,必须先安装 B,而安装 B 需要先安装 C;解决此类型依赖的方法是从后往前安装,即先安装 D,再安装 C,然后安装 B,最后安装软件 A。
环形依赖(A-B-C-D-A):各个软件安装的依赖关系构成环状。解决此类型依赖的方法是用一条命令同时安装所有软件包,即使用 rpm -ivh A B C D

已上两种依赖关系,都是通过手动安装方式解决,非常繁琐,如果依赖的包特别多,明显不适用。在下一讲中,将学习使用 yum 命令查询、安装、升级和卸载软件包的方法。它可以自动处理软件包之间的依赖性关系,一次性安装所有依赖的软件包,无需一个个安装。

版本要求
例如装gcc 这个软件包的时候,会有如下输出:
[root@prometheus Packages]# rpm -ivh gcc-4.8.5-44.el7.x86_64.rpm
error: Failed dependencies: <— 提示依赖性错误
cpp = 4.8.5-44.el7 is needed by gcc-4.8.5-44.el7.x86_64
glibc-devel >= 2.2.90-12 is needed by gcc-4.8.5-44.el7.x86_64
libmpc.so.3()(64bit) is needed by gcc-4.8.5-44.el7.x86_64
libmpfr.so.4()(64bit) is needed by gcc-4.8.5-44.el7.x86_64
提示要安装 gcc,需要先安装其他包,这就是RPM 包的依赖性。
另外信息中还会明确给出各个依赖软件的版本要求:
“>=”:表示版本要大于或等于显示版本;
“<=”:表示版本要小于或等于显示版本;
“=”:表示版本要等于显示版本;

下面我们会详细讲解 RPM包的使用,请熟练掌握

RPM包管理系统

RPM包命名规则

RPM 包的命名具有规则,用户通过名称可获取包的版本、适用平台等信息。
RPM包命名格式如下:
包名-版本号-发布次数-发行商-Linux平台-适合的硬件平台-包扩展名
例如:libreport-web-2.1.11-53.el7.centos.x86_64.rpm

选项含义
libreport-web软件包名。
2.1.11包的版本号,版本号的格式通常为主版本号.次版本号.修正号。
53包发布的次数,表示此 包是第几次编程生成的。
el*:软件发行商,el7 表示是由 Red Hat 公司发布,在 RHEL 7.x 和 CentOS 7.x 上使用。
Centos这个软件包适用的平台,其它软件包可能不包含这个选项
x86_64包能够使用的硬件平台,参照下面列表。x86_64代表在64位的操作系统上安装运行

包名和包全名

包名是指版本号之前的字符串。包全名是指带rpm完整字符串的名称。

  1. 例 libreport-web-2.1.11-53.el7.centos.x86_64.rpm
    这个文件它的包名是 libreport-web
    它的包全名是 libreport-web-2.1.11-53.el7.centos.x86_64.rpm。
    注意:包名和包全名,两者是不同的。软件包的安装和升级是需要指定包全名。而软件查询卸载是使用包名。一定要区分开!

  2. 例Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64.rpm
    这个文件的包名是Percona-Server-server-56 注意不是Percona-Server-server
    它的包全名是 Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64.rpm

[root@zaishu ~]# rpm -qa Percona-Server-server  //没有输出
[root@zaishu ~]# rpm -qa Percona-Server-server-56  
Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64
[root@zaishu ~]# rpm -qi Percona-Server-server-56
Name        : Percona-Server-server-56  //包名
Version     : 5.6.38
Release     : rel83.0.el7
Architecture: x86_64
Install Date: Mon 15 Nov 2021 12:02:23 PM CST
Group       : Applications/Databases
Size        : 92247229
License     : Copyright (c) 2000, 2010, Oracle and/or its affiliates.  All rights reserved.  Use is subject to license terms. Under the GNU General Public License (http://www.gnu.org/licenses/).
Signature   : DSA/SHA1, Fri 08 Dec 2017 05:28:46 PM CST, Key ID 1c4cbdcdcd2efd2a
Source RPM  : Percona-Server-56-5.6.38-rel83.0.el7.src.rpm
Build Date  : Fri 08 Dec 2017 05:27:16 PM CST
Build Host  : os-centos-7-x64-4119.ci.percona.com
Relocations : (not relocatable)
Packager    : Percona MySQL Development Team <mysqldev@percona.com>
Vendor      : Percona, Inc
URL         : http://www.percona.com/
Summary     : Percona Server: a very fast and reliable SQL database server

硬件平台

注意:32位的包可以安装在x86_64中,但64位的包是不能够安装在32位的操作系统中。

平台适用平台信息
i386386 以上计算机都可以安装
i586686 以上计算机都可以安装
i686奔腾 II 以上的计算机都可以安装,对于32位的操作系统目前基本都是这个居多
x86_6464 位 CPU 可以安装
noarch没有硬件限制
例如当前安装的是64位centos,所以安装盘中主要都是x86_64的包
[root@prometheus Packages]# ls *x86_64* | wc -l
2665
还有一些包就是noarch,表示对硬件没有限制
[root@prometheus Packages]# ls *noarch* | wc -l
1405

RPM常见选项

语法可以通过man rpm具体查看,这节只列出常用的一些选项

选项用途
-a查询所有包。
-c只列出包的配置文件,本参数需配合"-l"参数使用。
-d只列出文本文件,本参数需配合"-l"参数使用。
-e<包档>或–erase<包档>删除指定的包。
-f<文件>+查询拥有指定文件的包。
-h或–hash包安装时列出标记。
-i显示包的相关信息。
-i<包档>或–install<包档>安装包。
-l显示包的文件列表。
-p<包档>+指定未安装的包。
-q查询包。
-R显示包的关联性信息。
-s显示文件状态,本参数需配合"-l"参数使用。
-U<包档>或–upgrade<包档>升级指定的包。
-v显示指令执行过程。
-vv详细显示指令执行过程,便于排错。

软件包查找

rpm 命令可用来对 RPM 软件包做查询操作,具体包括:

查询包是否已安装;
查询所有已安装的包;
查看包的详细信息;
查询包的文件列表;
查询文件具体属于哪个包。

rpm -q 查询软件包是否安装

查询包是否安装:
[root@localhost ~]# rpm -q 包名
-q 表示查询,是 query 的首字母。
例如,查看 Linux 系统中是否安装 apache:

[root@prometheus Packages]# rpm -q httpd
httpd-2.4.6-97.el7.centos.2.x86_64

这里使用的是包名,而不是包全名。

rpm -qa:查询所有安装的包

查询 Linux 系统中所有已安装软件包:

[root@zaishu ~]# rpm -qa
glibc-devel-2.17-324.el7_9.x86_64
perl-Filter-1.49-3.el7.x86_64
libcurl-7.29.0-59.el7_9.1.x86_64
readline-devel-6.2-11.el7.x86_64
python-libs-2.7.5-90.el7.x86_64
…省略…

也可以使用管道符查找:

[root@prometheus Packages]# rpm -qa|grep httpd
httpd-2.4.6-97.el7.centos.2.x86_64
httpd-tools-2.4.6-97.el7.centos.2.x86_64

rpm -qi:查询包的详细信息

查询软件包的详细信息,-i 选项表示查询软件信息:
[root@localhost ~]# rpm -qi 包名

[root@zaishu ~]# rpm rpm -qi Percona-Server-client-56
Name        : rpm
Version     : 4.11.3
Release     : 45.el7
Architecture: x86_64
Install Date: Thu 08 Oct 2020 07:57:46 PM CST
Group       : System Environment/Base
Size        : 2622621
License     : GPLv2+
Signature   : RSA/SHA256, Thu 15 Oct 2020 03:00:03 AM CST, Key ID 24c6a8a7f4a80eb5
Source RPM  : rpm-4.11.3-45.el7.src.rpm
Build Date  : Thu 01 Oct 2020 01:30:03 AM CST
Build Host  : x86-02.bsys.centos.org
Relocations : (not relocatable)
Packager    : CentOS BuildSystem <http://bugs.centos.org>
Vendor      : CentOS
URL         : http://www.rpm.org/
Summary     : The RPM package management system
..........
For a description of Percona Server see http://www.percona.com/software/percona-server/

rpm -qip 查看未安装包的详细信息

查询未安装软件包的详细信息,命令格式为:
[root@localhost ~]# rpm -qip 包全名 //-p 表示未安装的软件包。
rpm -qip zziplib-utils-0.13.62-9.el7.x86_64.rpm

[root@prometheus Packages]# rpm -qip  zziplib-0.13.62-12.el7.x86_64.rpm 
Name        : zziplib
Version     : 0.13.62
Release     : 12.el7
Architecture: x86_64
Install Date: (not installed)
Group       : Applications/Archiving
Size        : 216046
License     : LGPLv2+ or MPLv1.1
Signature   : RSA/SHA256, Sat 04 Apr 2020 05:10:34 AM CST, Key ID 24c6a8a7f4a80eb5
Source RPM  : zziplib-0.13.62-12.el7.src.rpm
Build Date  : Wed 01 Apr 2020 01:04:24 PM CST
Build Host  : x86-01.bsys.centos.org
Relocations : (not relocatable)
Packager    : CentOS BuildSystem <http://bugs.centos.org>
Vendor      : CentOS
URL         : http://zziplib.sourceforge.net/
Summary     : Lightweight library to easily extract data from zip files
Description :
The zziplib library is intentionally lightweight, it offers the ability to
easily extract data from files archived in a single zip file. Applications
can bundle files into a single zip archive and access them. The implementation
is based only on the (free) subset of compression with the zlib algorithm
which is actually used by the zip/unzip tools.

rpm -ql:查询已安装包 产生的文件列表

rpm包安装后采用默认的路径,安装后的文件会分类安放在不同目录下。使用 rpm 命令可以查询到包安装后产生的所有文件和路径:
[root@localhost ~]# rpm -ql 包名
-l :列出软件包所有文件的安装目录。

例如安装apache后,查询这个包中所有文件和位置:

[root@zaishu~]# rpm -ql httpd
/etc/httpd
/etc/httpd/conf
/etc/httpd/conf.d
/etc/httpd/conf.d/README
/etc/httpd/conf.d/welcome.conf
/etc/httpd/conf/httpd.conf
/etc/httpd/conf/magic
…省略部分输出…

rpm -qlp:查询未安装包 安装后产生的文件列表

rpm 命令还可以查询 未安装的包 所含有的文件以及安装后的路径:
-p :未安装的软件包。
例如查看尚未安装的bind包中的所有文件及安装后的位置,可以执行如下命令:

[root@prometheus Packages]# rpm -qlp bind-9.11.4-26.P2.el7.x86_64.rpm 
/etc/NetworkManager/dispatcher.d/13-named
/etc/logrotate.d/named
/etc/named
/etc/named.conf
/etc/named.iscdlv.key
/etc/named.rfc1912.zones
…省略部分输出…

rpm -qf 查询文件系统(命令)属于哪个包

支持反向查询,用于查询文件属于哪个包,特别是在查询命令或者卸载命令的时候,这个参数用的比较频繁:
[root@zaishu~]# rpm -qf 系统文件名
-f 选项的含义是查询系统文件所属哪个软件包,是 file 的首字母。

例 ls 命令所属的包:

[root@zaishu ~]# which ls
alias ls='ls --color=auto'
	/usr/bin/ls
[root@zaishu ~]# rpm -qf /usr/bin/ls
coreutils-8.22-24.el7.x86_64
以后想删掉ls这条命令的时候,就可以通过卸载coreutils-8.22-24.el7.x86_64来实现

rpm -qR:查询软件包的依赖关系

安装包的时候需考虑与其他包的依赖关系。rpm -qR 用来查询已安装包的依赖关系,该命令的格式为:
[root@localhost ~]# rpm -qR 包名
-R(大写)选项的含义是查询软件包的依赖性,是 requires 的首字母。
例如,查询 apache 软件包的依赖性,可执行以下命令:

[root@zaishu ~]# rpm -qR httpd
/bin/bash
/bin/sh
/etc/mime.types
/usr/sbin/useradd
apr-util-ldap
chkconfig
config(httpd) = 2.4.6-97.el7.centos.2
httpd-tods = 2.4.6-97.el7.centos.2
…省略部分输出…

rpm -qRp:查询未安装包的依赖关系

同样,在此命令的基础上增加 -p 选项,即可实现查找未安装软件包的依赖性。
例如,bind 软件包尚未安装查看此软件包的依赖性可执行如下命令:

[root@zaishu Packages]# rpm -qRp bind-9.9.4-72.el7.x86_64.rpm
/bin/bash
/bin/sh
bind-libs = 32:9.8.2-0.10.rc1.el6
chkconfig
chkconfig
config(bind) = 32:9.8.2-0.10.rc1.el6
grep
libbind9.so.80
libc.so.6
libc.so.6(GLIBC_2.0)
libc.so.6(GLIBC_2.1)

RPM安装

包的安装

rpm -ivh 包全名 ;
注意: 这儿一定要使用包全名,不是包名。

rpm -ivh 包全名
-i:安装(install);
-v:显示更详细的信息(verbose);
-h:打印 #,显示安装进度(hash);

例:安装 Percona-Server-shared软件包

[root@zaishu ~]# rpm -ivh Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64.rpm
warning: Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID cd2efd2a: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:Percona-Server-shared-56-5.6.38-r################################# [100%]

第一个 100% 表示完成了准备工作;第二个100%表示安装完成。对于已经安装的包,只会有准备的那个100%

[root@zaishu ~]# rpm -ivh Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64.rpm
warning: Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID cd2efd2a: NOKEY
Preparing...                          ################################# [100%]
	package Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64 is already installed

例: 安装多个软件包

[root@zaishu ~]# rpm -ivh Percona-Server-client-56-5.6.38-rel83.0.el7.x86_64.rpm  Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64.rpm 
warning: Percona-Server-client-56-5.6.38-rel83.0.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID cd2efd2a: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:Percona-Server-client-56-5.6.38-r################################# [ 50%]
   2:Percona-Server-server-56-5.6.38-r################################# [100%]

其他参数选项

如果还有其他安装要求(比如强制安装某软件而不管它是否有依赖性),可以通过以下选项进行调整:

选项含义
-nodeps不检测依赖性安装。软件安装时会检测依赖性,确定所需的底层软件是否安装,如果没有安装则会报错。如果不管依赖性,想强制安装,则可以使用这个选项。注意,这样不检测依赖性安装的软件基本上是不能使用的,所以不建议这样做。
-replacefiles替换文件安装。如果要安装软件包,但是包中的部分文件已经存在,那么在正常安装时会报"某个文件已经存在"的错误,从而导致软件无法安装。使用这个选项可以忽略这个报错而覆盖安装。
-replacepkgs替换软件包安装。如果软件包已经安装,那么此选项可以把软件包重复安装一遍。
-force:强制安装。不管是否已经安装,都重新安装。也就是 -replacefiles 和 -replacepkgs 的综合。
-test测试安装。不会实际安装,只是检测一下依赖性。
-prefix指定安装路径。为安装软件指定安装路径,而不使用默认安装路径。

例 -nodeps: 不检测依赖

可以看到当正常安装Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64.rpm的时候,提示需要其他两个包,这就是依赖性,需要先安装Percona-Server-client-56和Percona-Server-shared-56才能安装Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64.rpm。
[root@zaishu ~]# rpm -ivh Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64.rpm 
warning: Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID cd2efd2a: NOKEY
error: Failed dependencies:
	Percona-Server-client-56 is needed by Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64
	Percona-Server-shared-56 is needed by Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64
如果加上 -nodeps ,表示不检查依赖性,直接安装。实际工作当中,是不建议这样安装,因为即使安装成功,也不代表这个包能够正常使用。
[root@zaishu ~]# rpm -ivh Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64.rpm  --nodeps
warning: Percona-Server-server-56-5.6.38-rel83.0.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID cd2efd2a: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:Percona-Server-server-56-5.6.38-r################################# [100%]

例 --force:强制安装

[root@zaishu ~]# rpm -ivh Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64.rpm 
warning: Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID cd2efd2a: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:Percona-Server-shared-56-5.6.38-r################################# [100%]

这个时候再安装,会提示已经安装

[root@zaishu ~]# rpm -ivh Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64.rpm 
warning: Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID cd2efd2a: NOKEY
Preparing...                          ################################# [100%]
	package Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64 is already installed

加上–force 表示会强制安装,替换软件包和文件

[root@zaishu ~]# rpm -ivh Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64.rpm --force
warning: Percona-Server-shared-56-5.6.38-rel83.0.el7.x86_64.rpm: Header V4 DSA/SHA1 Signature, key ID cd2efd2a: NOKEY
Preparing...                          ################################# [100%]
Updating / installing...
   1:Percona-Server-shared-56-5.6.38-r################################# [100%]

RPM包安装路径

RPM 包安装后的默认路径列表。所有安装文件会按照下面分类放置在不同的目录之中。

安装路径含 义
/etc/配置文件安装目录
/usr/bin/可执行的命令安装目录
/usr/lib/程序所使用的函数库保存位置
/usr/share/doc/基本的软件使用手册保存位置
/usr/share/man/帮助文件保存位置

RPM 包的默认安装路径通过命令查询的。
RPM 包可以人为指定安装路径,但不推荐。因为手工指定的路径,系统中用来查询安装路径的命令无法自动识别使用。

[root@zaishu ~]# rpm -ql Percona-Server-server-56
/etc/logrotate.d/mysql
/usr/bin/innochecksum
....
/usr/bin/resolveip
/usr/lib/systemd/system/mysqld.service
..
/usr/lib64/mysql/plugin/adt_null.so
...
/usr/lib64/mysql/plugin/validate_password.so
/usr/sbin/mysqld
...
/usr/sbin/rcmysql
/usr/share/doc/Percona-Server-server-56-5.6.38
...
/usr/share/percona-server/ukrainian/errmsg.sys
....

注意: 后面在讲解源码包编译安装方式的时候,会手工指定安装路径。但二进制包不要画蛇添足时指定安装路径。

RPM包的升级

语法:
[root@localhost ~]# rpm -Uvh 包全名
-U(:如果该软件没安装过则直接安装;若已有安装则升级至最新版本。
[root@localhost ~]# rpm -Fvh 包全名
-F:如果该软件没有安装,不会安装,必须有较低版本才能升级。

RPM包的卸载

语法:
[root@localhost ~]# rpm -e 包名 [-nocteps]
-e : erase 首字母,表示卸载。
-nocteps : 不检查依赖直接卸载。不建议使用~

rpm -e 卸载包

[root@zaishu ~]# rpm -e Percona-Server-server-56

依赖性

RPM 软件包的卸载要考虑包之间的依赖性。例如,我们先安装的 httpd 软件包,后安装 httpd 的功能模块 mod_ssl 包,那么在卸载时,就必须先卸载 mod_ssl,然后卸载 httpd,否则会报错。
软件包卸载和拆除大楼是一样的,本来先盖的 2 楼,后盖的 3 楼,那么拆楼时一定要先拆除 3 楼。
如果卸载 RPM 软件不考虑依赖性,执行卸载命令会包依赖性错误,例如:

[root@node1 Packages]# rpm -e httpd
error: Failed dependencies:
	httpd = 2.4.6-88.el7.centos is needed by (installed) httpd-devel-2.4.6-88.el7.centos.x86_64
	httpd = 2.4.6-88.el7.centos is needed by (installed) httpd-manual-2.4.6-88.el7.centos.noarch

[root@node1 Packages]# rpm -e httpd-devel
[root@node1 Packages]# rpm -e httpd-manual
[root@node1 Packages]# rpm -e httpd
[root@node1 Packages]# rpm -qa|grep httpd
httpd-tools-2.4.6-88.el7.centos.x86_64
[root@node1 Packages]# rpm -e httpd-tools

卸载命令

当想删除一条命令的时候,可能更多是想将这个命令对应的软件进行卸载,彻底删除这条命令。

查找命令的绝对路径
[root@node1 ~]# which samba-regedit   
/usr/bin/samba-regedit
查找这条命令对应的包,需要提供绝对路径
[root@node1 ~]# rpm -qf /usr/bin/samba-regedit 
samba-client-4.8.3-4.el7.x86_64
卸载包
[root@node1 ~]# rpm -e samba-client

RPM包验证和数字证书

系统中有非常多的RPM 包,每个包安装后又有大量的文件。因此这些包或者文件都有可能被修改或删除。为了能及时发现文件做了变更或者被人恶意篡改文件等问题,系统提供了两种检测方式:

  1. 包校验:将已安装文件和 /var/lib/rpm/ 下的的数据库进行比较,来确定文件是否被修改。
  2. 包数字证书校验:用来校验 包本身是否被修改。

Linux RPM 包校验

包校验用来判断已安装的软件包(或文件)是否被修改,此方式可使用的命令格式分为以下 3 种。

[root@zaishu~]# rpm -Va
-Va 选项表示校验系统中已安装的所有软件包。
[root@zaishu~]# rpm -V 已安装的包名
-V 选项表示校验指定 RPM 包中的文件,是 verity 的首字母。
[root@zaishu~]# rpm -Vf 系统文件名
-Vf 选项表示校验某个系统文件是否被修改。

例1. 对安装后的文件做修改
apache 软件包中所有的安装文件是否被修改,可执行如下命令:

当不做任何变更的时候,如果没有输出表示没有做修改
[root@localhost -]# rpm -V httpd  

apache 的配置文件 /etc/httpd/conf/httpd.conf 进修改后;再验证这个包

[root@node1 conf]# rpm -V httpd
S.5....T.  c /etc/httpd/conf/httpd.conf

可以看到,结果显示httpd.conf这个文件修改过。输出的信息可分为以下 3 部分:分别是验证信息,文件类型,文件名称。

第一列是验证信息
最前面的 8 个字符(S.5…T)都属于验证信息,每列含义如下:

第一列:S.5…T.
S文件大小是否改变。 出现S表示文件大小改变了
M文件的类型或文件的权限(rwx)是否改变。
5文件MD5校验和是否改变(可以看成文件内容是否改变)。
D设备的主从代码是否改变。
L文件路径是否改变。
U文件的属主(所有者)是否改变。
G文件的属组是否改变。
T文件的修改时间是否改变。
.若相关项没发生改变,用 . 表示。
通过验证信息可以知道这个文件的大小和md5码,mtime都变更过。

第二列是文件类型
分为以下几类:

字符含义
c配置文件(configuration file)。
d普通文档(documentation)。
g"鬼"文件(ghost file),很少见,就是该文件不应该被这个 RPM 包包含。
l授权文件(license file)。
r描述文件(read me)。

第三列是文件名称
被修改文件所在绝对路径和文件名。

因此S.5…T. c /etc/httpd/conf/httpd.conf 表达的完整含义是:配置文件 httpd.conf 的大小、内容、修改时间被人为修改过。
注意:通常修改配置文件是正常的情况,需要留意是那些被恶意修改过文件。

Linux RPM数字证书验证

之前方法是验证已经安装包后相关文件信息。如果在安装前,rpm包已经被修改,不是厂家提供的包,这个时候需要使用 RPM 数字证书来验证。
数字证书,又称数字签名,由软件开发商直接发布。Linux 系统安装数字证书后,若 RPM 包做了修改,此包携带的数字证书也会改变,将无法与系统匹配,软件无法安装。
可以将数字证书想象成自己的签名,是不能被模仿的(厂商的数字证书是唯一的)
使用数字证书验证 RPM 包的方法具有如下 2 个特点:

  1. 需要找到原厂的公钥文件,才能进行安装。
  2. 安装 RPM 包会提取包中证书信息,然后安装的原厂证书进行验证。验证通过,允许安装;验证失败,不允许安装并发出警告。

#系统中的数字证书位置

[root@node1 conf]# ll /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 
-rw-r--r--. 1 root root 1690 Nov 23  2018 /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

安装数字证书

[root@node1 conf]# rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
--import表示导入数字证书
数字证书安装完成后,可使用如下命令进行验证:
 [root@node1 conf]# rpm -qa|grep gpg-pubkey**
gpg-pubkey-f4a80eb5-53a7ff4b

查询数字证书
数字证书也是一个包,可以用 rpm 命令查询数字证书的详细信息:

[root@node1 conf]# rpm -qi  gpg-pubkey-f4a80eb5-53a7ff4b
#查询数字证书包的详细信息
...
-----END PGP PUBLIC KEY BLOCK----

卸载数字证书
使用 -e 选项:

[root@node1 conf]# rpm -e  gpg-pubkey-f4a80eb5-53a7ff4b
虽然数字证书可以手动卸载,但不推荐大家将其卸载。

安装数字证书后。在系统上安装 RPM 包时,系统会自动验证包的数字证书,验证通过则可以安装,
反之将无法安装(系统会报错)。

RPM包的数据库

系统中安装的所有RPM包,信息会保存到 RPM 数据库中,用户在使用 rpm 命令对执行查询、安装和卸载等操作的时候,会通过这个数据库中得到相关信息。

重建RPM包的数据库

在实际操作过程中有可能有一些操作导致数据库损坏,例如升级过程强行退出、安装时候意外中断,甚至误删除数据库等操作,都可能导致数据库出现故障。 后续再使用rpm命令的时候,由于数据库出现故障,请求无法执行。这时需要重建数据库,操作步骤如下:

删除已损坏的数据库,执行如下命令:

[root@zaishu ~]# ls /var/lib/rpm/
Basenames     __db.001      __db.003      Dirnames      Installtid    Obsoletename  Providename   .rpm.lock     Sigmd5        
Conflictname  __db.002      .dbenv.lock   Group         Name          Packages      Requirename   Sha1header    Triggername   
[root@zaishu ~]# rm -rf /var/lib/rpm/__db* //删除已损坏的数据库
[root@zaishu ~]# ls -l /var/lib/rpm/__db*
ls: cannot access /var/lib/rpm/__db*: No such file or directory

重建 RPM 数据库,执行如下命令:

[root@zaishu ~]# rpm -rebuilddb  //这一步花费一定时间。
[root@zaishu ~]#  ls -l /var/lib/rpm/__db*
-rw-r--r-- 1 root root  270336 Nov 15 15:44 /var/lib/rpm/__db.001
-rw-r--r-- 1 root root   81920 Nov 15 15:44 /var/lib/rpm/__db.002
-rw-r--r-- 1 root root 1318912 Nov 15 15:44 /var/lib/rpm/__db.003

人为修改数据库

为了不想让管理员 通过包校验检查出软件异常,进而手工修改数据库。对于这种情况,可以按照以下步骤对文件进行检测:

对于要校验的文件或命令,找到它属于哪个软件包,如下命令所示:

[root@node1 ~]# rpm -qf /etc/pam.d/samba
samba-4.8.3-4.el7.x86_64

使用 -dump 选项查看每个文件的信息,使用 grep 命令提取对应文件信息:

rpm -ql --dump samba|grep /etc/pam.d/samba,输出结果中 177表示 smb 文件最初的字符数。
adf2c510d4218ac0b3f72898cfe4097c0d1c9836da2b0237929af6bf4619ea84表示 文件的 MD5 校验值。
0644 root root表示文件权限及所有者、所属组。

查看文件,通过对比文件大小,所有人、所属组、权限、MD5 校验值等数据,判断文件是否改动过:

[root@node1 ~]# md5sum /etc/pam.d/samba 
c8d4d43f8a3f06190fcf32ff7e8b87b5  /etc/pam.d/samba

以上校验结果显示,系统的 /etc/rc.d/init.d/smb 文件的信息和通过 rpm-ql-dump Samba 命令获取的信息不一致,因此可以断定此文件没有被更改过。


总结

本小节会详细介绍linux中的软件包管理,涉及软件包的定义/安装/卸载/依赖等操作。以及会详细演示rpm这个非常重要命令的使用。

友情链接

MySQL性能优化_原理_实战

1、MySQL在金融互联网行业的企业级安装部署

目录章节
版本说明版本说明
安装MySQL规范1 安装方式
2 安装用户
3 目录规范
MySQL 5.7 安装部署1 操作系统配置
2 创建用户
3 创建目录
4 安装
5 配置文件
6 安装依赖包
7 配置环境变量
8 初始化数据库
9 重置密码
MySQL8 安装MySQL8 安装
源码安装1 安装依赖包
2 生成源码包
3 创建用户
4 编译安装
5 配置数据库
6 连接mysql
多实例部署及注意事项1 多实例概念
2 多实例安装
3 mysqld_multi(多实例第二种安装方式)

2、mysql启动关闭原理和实战_及常见错误排查

目录章节
生产中MySQL启动方式1、 启动原理
2、参数文件默认位置及优先级
3、 以server方式启动
4、 mysqld_safe方式
5、 mysqld 方式
6、 systemctl 方式
关库1、相关参数innodb_fast_shutdown
2、相关参数innodb_force_recovery
3、关闭mysql多种方式
常见MySQL启动失败案例1.、目录权限
2、参数问题
3、配置文件
4、端口占用
5、误删二进制文件
6、undo表空间异常
7、binlog缓冲异常
MySQL启动失败排查方法MySQL启动失败排查方法
连接MySQL数据库的方式连接MySQL数据库的方式
MySQL数据库用户安全策略1、初始化数据库
2、修改密码
3、删除无用的用户
4、mysql_secure_installation
找回丢失的用户密码找回丢失的用户密码

3、MySQL字符集和校对规则

目录章节
MySQL字符集和校验规则MySQL字符集和校验规则
查看字符集方法1、查看mysql支持的字符集
2、查看字符集的校对规则
3、查看当前数据库的字符集
4、查看当前数据库的校对规则
MySQL字符集设置1、字符集设置层级关系
2、设置MySQL服务器级别字符集
3、设置创建对象的字符集
字符集案例1、常用字符集每个汉字占用字节多少
2、大小案例
插入中文乱码解决插入中文乱码解决
数据库常见字符集及如何选择字符集数据库常见字符集及如何选择字符集
生产中如何彻底避免出现乱码生产中如何彻底避免出现乱码

4、史上最详细的Mysql用户权原理和实战_生产案例

目录章节
访问控制1、连接验证(阶段一)
2、允许的连接
3、连接优先级
4、请求验证(阶段二)
用户管理1、新增用户
2、修改用户
3、删除用户
4、查看用户
密码管理1、密码修改
2、密码过期设置
3、set password
4、密码过期策略
5、密码插件
MySQL用户权限管理1、权限粒度
2、显示账户权限
3、显示账户非权限属性
4、库级权限
5、表级权限
6、列级权限
7、权限回收
资源限制1、用户创建指定配额
2、修改配额
MySQL用户权限案例1、断掉已清理的用户
2、忘记密码
3、如何禁止一个ip段的某个用户登录
4、创建开发账号
5、创建复制账号
6、创建管理员账号

5、InnoDB引擎原理和实战_通俗易懂

目录章节
缓冲池1、默认引擎
2、设置缓冲池大小
3、优化缓冲池
4、管理缓冲池
5、数据页类型
线程1、IO线程
2、主线程
index pageindex page
insert buffer pageinsert buffer page
重做日志重做日志
回滚日志回滚日志
checkpoint,刷写脏页check pointcheckpoint
关键特性1、插入缓冲
2、数据写入可靠性提升技术-doublewrite
3、自适应哈希索引-AHI
innodb预读预写技术预读写

6、MySQL文件详解_物理结构_逻辑结构_原理和案例

目录章节
参数和配置文件1、文件位置
2、查找参数
3、参数类型
4、参数修改
5、示例一
6、示例二
7、注意事项
错误日志文件错误日志
通用日志通用日志
慢查询日志慢日志
binlog1、记录什么
2、用途
3、开启和参数配置
4、日志查看
5、日志刷新
6、删除日志
7、日志分析(mysqlbinlog)
8、利用二进制日志文件恢复误删的表
InnoDB存储引擎表空间文件表空间文件
主从同步相关文件主从同步文件
套接字文件套接字文件
pid 文件pid 文件
redo log1、redo初识
2、日志组
3、与oracle redo的区别
4、相关参数
5、和binlog的区别
6、redo 缓冲区(innodb_flush_log_at_trx_commit)
InnoDB存储引擎逻辑结构1、表空间
2、段
3、区
4、页
表碎片清理1、判断是否有碎片
2、整理碎片
表空间文件迁移1、需求
2、操作

7、SQL编程开发与优化事项

目录章节
常用语句1、导入数据
2、库操作
3、表操作
4、数据操作
5、use性能影响
6、delete、truncate、drop的区别
7、SQL语句分类
数据类型与性能1、整型
2、浮点型
3、字符串类型
4、日期类型
MySQL约束1、unsigned/signed
2、not null
3、count(*) 为什么慢
4、default
5、unique
6、 auto_increment
7、primary key
SQL编程高级1、查询Syntax
2、查询列
3、where子句
4、group by … having子句
5、order by子句
6、limit子句(分页)
7、聚合函数
8、合并查询
9、多表查询
10、子查询
表的元数据库管理1、统计应用库哪些表没有使用innodb存储引擎
2、如何查看表中是否有大对象
3、统计数据库大小
4、统计表的大小

8、MySQL索引原理和案例

目录章节
MySQL索引与二分查找法1、什么是索引
2、索引的优缺点
3、索引的最大长度
4、二分查找法:折半查找法
5、mysql一张表存多少数据后,索引性能就会下降?
剖析b+tree数据结构1、B和B+树的区别
2、索引树高度
3、非叶子节点
4、指针
5、叶子节点
6、双向指针
7、b+tree插入操作
8、b+tree删除操作
相辅相成的聚集索引和辅助索引1、聚集索引
2、聚集索引特点
3、聚集索引的优势
4、辅助索引
覆盖索引与回表查询1、回表查询
2、覆盖索引
创建高性能的主键索引1、主键索引创建的原则
2、主键索引的特点
3、为什么建议使用自增列作为主键
唯一索引与普通索引的性能差距1、唯一索引特点
2、普通索引特点
3、唯一索引与普通索引的性能差距
前缀索引带来的性能影响1、作用
2、坏处
如何使用联合索引1、什么是联合索引
2、创建原则
3、排序
Online DDL影响数据库的性能和并发1、5.6版本之前
2、新版本
3、online ddl语法
4、相关参数
5、示例
6、影响
pt-ocs原理与应用1、安装pt-osc
2、pt-osc语法
3、案例
4、pt-osc原理
生产中索引的管理1、建表时创建索引
2、建表后创建索引
3、查看索引
SQL语句无法使用索引的情况1、where条件
2、联合索引
3、联表查询
4、其他情况

9、information_schema和sys中性能查看

目录章节
最常用的STATISTICS和TABLES1、STATISTICS:用于存放索引的信息
2、TABLES:用于存放库表的元数据信息
判断索引创建是否合理1、选择性
2、索引创建的建议
检查联合索引创建是否合理1、联合索引创建是否合理
2、有了联合索引(a,b),还需要单独创建a索引吗?
如何查找冗余索引查找冗余索引
查找产生额外排序的sql语句额外排序的sql语句
查找产生临时表的sql语句临时表的sql语句
全表扫描的sql语句全表扫描的sql语句
统计无用的索引无用的索引
索引统计信息1、存储索引统计信息
2、如何查看索引统计信息

10、MySQL优化器算法与执行计划

目录章节
简单嵌套查询算法-simple nested-loop joinsimple nested-loop join
基于索引的嵌套查询算法-index nested-loop joinindex nested-loop join
基于块的嵌套查询算法- block nested-loop joinblock nested-loop join
Multi-Range ReadMRR
bached key access joinBKA
mysql三层体系结构体系结构
Index Condition Pushdown索引条件下推
一条查询SQL语句是怎样运行的查询SQL语句
一条更新SQL语句是怎样运行的更新SQL语句
MySQL长连接与短连接的选择1、相关参数
2、断开连接
执行计划explain1、语法
2、执行计划解析

11、MySQL查询优化

目录章节
MySQL查询优化技术概览
子查询优化1、优化器自动优化
2、优化措施:子查询合并
3、优化措施:子查询上拉技术
外连接消除外连接消除
生产环境不使用join联表查询不使用join
group by分组优化1、group by执行流程
2、为什么group by要创建临时表
order by排序优化排序优化
MySQL性能抖动问题性能抖动问题
count(*)优化count(*)优化
磁盘性能基准测试1、安装sysbench
2、生成文件
3、测试文件io
4、清除文件
MySQL基准测试1、生成数据
2、测试(读)
3、测试(写)
4、清理数据

12、事务原理和实战

目录章节
认识事务认识事务
事务控制语句1、开启事务
2、事务提交
3、事务回滚
事务的实现方式1、原子性
2、一致性
3、隔离性
4、持久性
purge thread线程purge thread线程
事务统计QPS与TPS1、QPS
2、TPS
事务隔离级别1、隔离级别
2、查看隔离级别
3、设置隔离级别
4、不同隔离级别下会产生什么隔离效果
事务组提交group commit组提交
事务两阶段提交两阶段提交
MVCC多版本并发控制1、MVCC原理
2、MVCC案例

13、锁的原理和应用

目录章节
认识锁1、锁的作用
2、加锁的过程
3、锁对象:事务
innodb行锁1、行锁类型
2、共享锁(S锁)
3、排他锁(X锁)
索引对行锁粒度的影响1、行锁粒度有哪些
2、在RC隔离级别下不同索引产生的锁的范围
3、RR隔离级别下不同索引产生锁的范围
FTWRL全局读锁FTWRL全局读锁
innodb表锁innodb表锁
innodb意向锁与MDL锁1、意向锁
2、意向锁作用
3、意向锁冲突情况
4、MDL锁
自增锁自增锁
插入意向锁插入意向锁
死锁1、什么是死锁
2、相关参数
3、避免死锁
4、锁的状态
两阶段锁协议两阶段锁协议

14、慢查询原理和实战_快速优化方法_优化工具

目录章节
1. 系统状态show status
2. 慢查询2.1 慢查询开启
2.2 简单示例
2.3 数据准备
3. mysqldumpslow3.1 语法
3.2 常见用法
4. pt-query-digest4.1 安装
4.2 语法选项
4.3 报告解读
4.4 用法示例
5. 优化工具(soar)5.1 安装配置
5.2 添加数据库
5.3 语句优化

15、备份恢复原理和实战_逻辑备份_物理备份_金融行业备份还原脚本

目录章节
1.生产中备份方式1.1 物理备份与逻辑备份
1.2 联机与脱机备份
1.3 完整备份与增量备份
1.4 常用命令
2.mysqldump备份2.1 相关参数
2.2 备份所有数据库
2.3 备份指定数据库
2.4 备份指定表
2.6 只导出结构
2.7 只导出数据
2.8 --tab(生成文本,类似load)
2.8 mysqldump原理
2.9 binlog异步备份
2.10 利用mysqldump全备及binlog恢复数据
3.xtrabackup3.1 Xtrabackup安装
3.2 原理
3.2 备份过程
3.4 恢复原理
3.3 相关参数
3.4 xtrabackup相关文件
3.5 备份示例
3.6 还原示例
4.binlog备份和恢复(数据库恢复)4.1 找到恢复时间点
4.2 增量恢复
5. 生产环境的备份恢复实战5.1 实施部署
5.1.1 环境清单
5.1.2 备份目的
5.1.3 备份说明
5.1.4 实施步骤
5.1.5 全备脚本
5.1.6 差异备份脚本
5.2 实施部署备份还原
5.2.1 Xtraback还原全量/差异备份
5.2.2 故障点数据恢复
5.2.3 增量恢复

16、主从复制,gtid,并行复制_半同步复制_实操案例_常用命令_故障处理

目录章节
1.认识主从复制1.1 主从复制原理深入讲解
1.2 主从复制相关参数
1.3.主从复制架构部署
1.4从库状态详解
1.5 .过滤复制
2 .gtid复制2.1 什么是GTID?
2.2 GTID主从配置
2.5 gtid维护
2.4 GTID的特点
2.3 工作原理
2.4 gtid相关状态行和变量
3. 并行复制3.1 延迟的原因
3.2 并行复制设置
3.3 查看并行复制
4. 增强半同步复制4.1 异步复制
4.2 半同步复制
4.3 增强半同步复制
4.4 配置增强半同步
5. 案例5.1 主库删除操作导致sql线程关闭案例
5.2 主从复制中断解决方案及案例
5.3 延迟复制
5.4 主库drop误操作利用延迟复制恢复案例
6 常用命令6.1 启动线程
6.2 关闭线程
6.3 查看
6.4 重置
6.5 主从数据一致性校验

17、MySQL高可用和读写分离架构
MHA

目录章节
MHA介绍
架构和相关组件架构和相关组件
工作流程工作流程
MHA高可用架构部署1、环境准备
2、软件安装
3、创建软链接
4、配置各节点互信
5、节点免密验证
6、mha管理用户
7、配置文件
8、状态检查
9、开启MHA
主库宕机故障模拟及处理主库宕机故障模拟及处理
MHA VIP自动切换VIP自动切换
MHA主从数据自动补足MHA主从数据自动补足

Atlas

目录章节
Atlas读写分离高性能架构介绍
安装配置安装配置
配置注解配置注解
启动和关闭启动和关闭
读写分离架构应用读写分离架构应用
创建应用用户创建应用用户
Atlas在线管理Atlas在线管理
读写分离避坑指南读写分离避坑指南

18、MySQL分库分表_原理实战

目录章节
1.MyCAT分布式架构入门及双主架构1.1 主从架构
1.2 MyCAT安装
1.3 启动和连接
1.4 配置文件介绍
2.MyCAT读写分离架构2.1 架构说明
2.2 创建用户
2.3 schema.xml
2.4 连接说明
2.5 读写测试
2.6 当前是单节点
3.MyCAT高可用读写分离架构3.1 架构说明
3.3 schema.xml(配置)
3.4 文件详解
3.4.1 schema标签
3.4.2 table标签
3.4.3 dataNode标签
3.4.4 dataHost
3.4 读写测试
3.5 故障转移
4.MyCAT垂直分表4.1 架构
4.2 新建表
4.3 配置mycat
4.4 验证
5 MyCAT水平分表-范围分片5.1 新建表
5.2 schema.xml
5.2 rule.xml
5.3 autopartition-long.txt
5.4 验证
6. MyCAT水平分表-取模分片取模分片
7. MyCAT水平分表-枚举分片枚举分片
8. MyCAT全局表与ER表全局与ER表
8.1 全局表8.1.1 特性
8.1.2 建表
8.1.3 配置
8.1.4 验证
8.1.5 分析总结(执行计划)
8.2 ER表8.2.1 特性
8.2.2 建表
8.2.3 配置
8.2.4 测试验证,子表是否跟随父表记录分片
8.2.5 分析总结(执行计划)

19、基准性能测试_sysbench

目录章节
1. sysbench1.1 用途
1.2 安装
1.3 版本
1.4 查看帮助
1.5 测试过程阶段
2 CPU 性能测试2.1 测试原理
2.2 查看帮助
2.3 测试
3. 内存性能测试3.1 查看帮助信息
3.2 测试过程
4.磁盘性能基准测试4.1 查看帮助
4.2 生成文件(prepare)
4.3 测试文件io(run)
4.4 结果分析
4.5 清除文件(cleanup)
5. 线程测试5.1 查看帮助信息
5.2 测试过程
6. MySQL基准测试6.1 语法参数
6.2 生成数据
6.3 测试(读)
6.4 测试(写)
6.5 清理数据
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值