RPM包管理器(RPM Package Manager,RPM)是一个功能强大的包管理系统,它能够:
在这一步,需要知道要将哪些内容打包成 RPM,是应用程序或补丁、编程库、系统配置文件或者是文档包?大多数情况下,我们需要创建一个源码包( source package)和一个二进制包(binary package)。二进制包包含可以在其它系统安装的 RPM,源码包可以随时重新创建二进制包,前提是已经定义了源 RPM(source RPM)。
收集要捆绑到 RPM 中的软件,这包括应用程序或要打包的库以及程序源代码。一般来说包含以下情况:
RPM 系统将自动执行创建应用程序的步骤,只要您配置 RPM 使用适当的步骤,例如使目标运行。不幸的是,配置适当的步骤并不总是容易的。因此,在尝试创建RPM之前,您需要弄清楚如何构建您计划打包到RPM中的应用程序或库。一旦您弄清楚如何构建应用程序或库,您可以设置可重复生成。然后,RPM系统可以自动执行此操作建立。
要构建软件,您需要使用各种Linux工具。您需要的特定工具很大程度上取决于原始软件的来源。了解这些软件的常用技术如下:
拆包软件,包括 tar、tar.gz、zip 等
阅读 README 文件,包括 README 文件可能的变体,INSTALL 及其变体文件
适用 Linux 构建工具构建程序,通常在 Linux,我们可能使用 make 工具,但前提是需要创建正确的 Makefile 文件,通常有以下几种方法:
手段创建,下载一个程序并找到这样的文件如 Makefile.amiga、Makefile.Solaris 和 Makafile.Linux,然后根据系统架构复制为 Makefile
imake,使用 ImakeFile 的配置文件,应用于基于 X Window 应用程序或操作系统,并大多数情况下自带通用构建脚本:
# 找到 ImakeFile 文件后,运行下面的命令来构建程序
xmkmf
make
make install
# xmkmf 是用于创建 Makefile 文件的脚本
# 如果 xmkmf 不可用或者不起作用,可能需要执行下面的命令
make Makefile
# 存在多个源代码目录时,可以执行
make Makefiles
# 了解更多:http://www.dubois.ws/software/imake-stuff/
配置脚本,configure 脚本输出一个特定于平台的 Makefile
# 如果在源文件中看到一个名为 configure 的文件,运行下面的命令来构建程序
./configure
make
make install
# configure 脚本由一组工具(包括 automake 和 autoconf)创建
# 这些工具使用通常名为 configure.in 和 makefile.am 的通用文件以及其他文件来创建通用配置脚本
# 通常情况下 configure 需要接收参数,比如 --prefix,用来指定构建应用程序的根目录
# 更多: https://www.airs.com/ian/configure/
构建 Perl 模块
# 如果在源码中看到一个 Makefile.PL 的文件,需要运行这些命令来构建应用程序或模块
perl Makefile.PL
make
make test
make install
以 RPM 格式打包的任何应用程序或库都可能在某个时候得到升级。当这种情况发生时,您需要创建一个新的 RPM。这个新的 RPM 不仅必须处理软件包的安装,还必须处理任何升级问题。您需要考虑以下问题:
执行 make 的时候,必须保证包含了所有的依赖项。在大多数情况下,我们不希望在 RPM 中包含依赖项。相反,每个依赖项每个必要的库都应该有自己的 RPM。在许多情况下,您应该能够找到 RPM 对于这些依赖关系,并跟踪提供依赖项的包。
构建 RPM 需要由 rpmbuild 命令来完成。构建 RPM,请执行以下步骤:
目录 | 使用 |
---|---|
BUILD | rpmbuild 命令在此目录中构建软件 |
RPMS | rpmbuild 命令将其创建的二进制 RPM 存储在此目录中,通常包含许多特定于体系结构的子目录,包括 athlon、i386、i486、i586、i686、noarch |
SOURCES | 将应用程序的源代码放在此目录中 |
SPECS | 将计划创建的每个 RPM 的 spec 文件放在此目录中 |
SRPMS | rpmbuild 命令将源 RPM 放置在此目录中 |
默认情况下,Red Hat Linux 系统期望在 /usr/src/redhat 目录中构建 RPM,这个目录显然是特定于 Red Hat Linux 的。在其他 Linux 发行版上,您可能会看到其他目录。
首先,使用系统目录来构建 RPM 似乎很奇怪。但请记住,RPM系统最初是为创建 Linux 发行版而构建的(可以通过修改 rpmrc 设置更改默认目录)。
目前,最简单的方法是切换到 /usr/src/redhat 目录并从该位置开始工作。首先,您需要更改这些文件的所有权或权限,以便您可以在以普通用户身份登录时构建RPM。不要在以 root 身份登录时构建 RPM。如果您以 root 身份登录,则构建包时的错误可能会导致严重的后果。
要构建RPM,实际上只需要两件事:
最好的策略是从自己创建的目录开始,从源代码创建 tarball(package-version.tar.gz)文件,然后将 tarball 文件复制到 /usr/src/redhat/sources 目录。
spec(Specification File)文件定义了 rpmbuild 命令构建应用程序时应执行的所有操作,以及 rpm 命令安装和删除应用程序所需的所有操作。每个源 RPM 都应具有构建二进制 RPM 所需的规范文件。
在 spec 文件中,使用特殊语法设置软件包上信息的格式。此语法定义如何构建包、版本号、依赖关系信息以及您可以查询的有关包的其他所有内容。根据 spec 文件中的部分,此语法略有不同。以下部分介绍了这些规范文件部分以及每个部分中的必要语法。
The introduction section
简介部分包含有关软件包的信息,即rpm-qi命令所显示的信息类型。例如:
Summary: java source to bytecode compiler
%define version 1.17
Copyright: IBM Public License, http://ibm.com/developerworks/oss/license10.html
Group: Development/Languages
Name: jikes
Prefix: /usr
Provides: jikes
Release: 1
Source: jikes-%{version}.tar.gz
URL: http://ibm.com/developerworks/opensource/jikes
Version: %{version}
Buildroot: /tmp/jikesrpm
%description
The IBM Jikes compiler translates Java source files to bytecode. It
also supports incremental compilation and automatic makefile generation,
and is maintained by the Jikes Project:
http://ibm.com/developerworks/opensource/jikes/
此示例来自真实的 RPM 规范文件。它并不遵循创建 RPM 的所有规则。此示例
The prep section
prep(prepare)部分定义了准备构建所需的命令。如果你从源代码的压缩 tar 存档(tarball)开始,prep部分需要提取文件。
%prep
%setup -q
此示例使用 %setup RPM宏来提取文件。
The build section
spec 文件包含构建软件的命令,通常,这将只包括几个命令,因为大多数实际指令都出现在 makefile 中。例如:
%build
./configure CXXFLAGS=-O3 --prefix=$RPM_BUILD_ROOT/usr
make
Build 部分以 %build 语句开头。
The install section
spec 文件install 部分包含安装新构建的应用程序或库所需的命令。在大多数情况下,您的安装部分应该清除 BuildRoot 目录并运行 make install命令。例如:
%install
rm -fr $RPM_BUILD_ROOT
make install
install 部分以 %install 语句开头。
The clean section
clean 部分清理其他部分中的命令创建的文件:
%clean
rm -rf $RPM_BUILD_ROOT
clean 部分以 %clean 语句开头。
The files section
files 部分列出了要进入二进制 RPM 的文件,以及已定义的文件属性。例如:
%files
%defattr(-,root,root)
/usr/bin/jikes
%doc /usr/doc/jikes-%{version}/license.htm
%doc /usr/man/man1/jikes.1*
files 部分以 %files 语句开头。
%doc 宏将某些文件标记为文档。这允许 RPM 将保存文档的文件与 RPM 中的其他文件区分开来。
编写了spec 文件并将其放在 /usr/src/redhat 下的 sources 和 specs 目录中后,将看到如下文件:
$ ls –CF /usr/src/redhat/*
/usr/src/redhat/BUILD:
/usr/src/redhat/RPMS:
athlon/ i386/ i486/ i586/ i686/ noarch/
/usr/src/redhat/SOURCES:
jikes-1.17.tar.gz
/usr/src/redhat/SPECS:
jikes.spec
/usr/src/redhat/SRPMS:
也就是说,在一个干净的系统中,没有构建其他RPM,将在 /usr/src/redhat/specs 中看到一个 spec 文件,在 /usr/src/redhat/sources 中看到源代码。在此示例中,源文件位于压缩的 tar 存档中(为此,RPM 规范文件 jikes.spec 需要在 prep 部分中有一个命令来提取文件)。
现在,准备好可以构建 RPM。
要使用 rpmbuild 命令构建 RPM,请使用以下基本语法:
rpmbuild -bBuildStage spec_file
-b 选项告诉 rpmbuild 构建 RPM。额外的 BuildStage 选项是一个特殊的代码,它告诉rpmbuild命令在构建时要走多远。选项包括:
选项 | 使用 |
---|---|
-ba | 构建所有,包括二进制和源 RPM |
-bb | 构建二进制 RPM |
-bc | 构建(编译)程序,但不进行完整的RPM,在%Build部分后立即停止 |
-bp | 准备构建二进制 RPM,并在完成 %prep 部分后立即停止 |
-bi | 创建二进制 RPM 并在 %install 部分后立即停止 |
-bl | 检查 RPM 的文件列表,如果 BuildRoot 缺少任何要安装的文件,则生成错误 |
-bs | 仅构建源RPM |
rpmbuild 命令参数说明:
[root@bogon /]# rpmbuild --help
Usage: rpmbuild [OPTION...]
Build options with [ <specfile> | <tarball> | <source package> ]:
-bp build through %prep (unpack sources and apply patches) from <specfile>
-bc build through %build (%prep, then compile) from <specfile>
-bi build through %install (%prep, %build, then install) from <specfile>
-bl verify %files section from <specfile>
-ba build source and binary packages from <specfile>
-bb build binary package only from <specfile>
-bs build source package only from <specfile>
-tp build through %prep (unpack sources and apply patches) from <tarball>
-tc build through %build (%prep, then compile) from <tarball>
-ti build through %install (%prep, %build, then install) from <tarball>
-ta build source and binary packages from <tarball>
-tb build binary package only from <tarball>
-ts build source package only from <tarball>
--rebuild build binary package from <source package>
--recompile build through %install (%prep, %build, then install) from <source package>
--buildroot=DIRECTORY override build root
--clean remove build tree when done
--nobuild do not execute any stages of the build
--nodeps do not verify build dependencies
--nodirtokens generate package header(s) compatible with (legacy) rpm v3 packaging
--noclean do not execute %clean stage of the build
--nocheck do not execute %check stage of the build
--rmsource remove sources when done
--rmspec remove specfile when done
--short-circuit skip straight to specified stage (only for c,i)
--target=CPU-VENDOR-OS override target platform
Common options for all rpm modes and executables:
-D, --define='MACRO EXPR' define MACRO with value EXPR
--undefine=MACRO undefine MACRO
-E, --eval='EXPR' print macro expansion of EXPR
--macros=<FILE:...> read <FILE:...> instead of default file(s)
--noplugins don't enable any plugins
--nodigest don't verify package digest(s)
--nosignature don't verify package signature(s)
--rcfile=<FILE:...> read <FILE:...> instead of default file(s)
-r, --root=ROOT use ROOT as top level directory (default: "/")
--dbpath=DIRECTORY use database in DIRECTORY
--querytags display known query tags
--showrc display final rpmrc and macro configuration
--quiet provide less detailed output
-v, --verbose provide more detailed output
--version print the version of rpm being used
Options implemented via popt alias/exec:
--with=<option> enable configure <option> for build
--without=<option> disable configure <option> for build
--buildpolicy=<policy> set buildroot <policy> (e.g. compress man pages)
--sign generate GPG signature (deprecated, use command rpmsign instead)
Help options:
-?, --help Show this help message
--usage Display brief usage message
Example:
# rpmbuild –bp specfile rpmbuild -bp /usr/src/redhat/SPECS/jikes.spec # rpmbuild -bb specfile rpmbuild -bb /usr/src/redhat/SPECS/jikes.spec # rpmbuild –bi specfile rpmbuild -bi /usr/src/redhat/SPECS/jikes.spec # rpmbuild –bs specfile rpmbuild -bs /usr/src/redhat/SPECS/jikes.spec # rpmbuild --clean specfile rpmbuild --clean /usr/src/redhat/SPECS/jikes.spec
构建 RPM 完成后,使用 rpmbuild 命令的 –bl 选项来验证 RPM 中的文件列表。
# rpmbuild –bl spec_file
rpmbuild -bl /usr/src/redhat/SPECS/jikes.spec
-bl 选项检查所有必要的文件是否都位于 buildroot 目录中。buildroot 目录是一个类似于最终安装的根目录的位置。
若出现错误,可以从头开始构建,或者使用 --short 选项从 spec 文件中给定的部分重新开始构建。在创建RPM时,需要在检测和修复错误时来回重新启动构建。
需要使用 rpm 命令与 –V 等选项一起使用,以验证完整构建的软件包。例如:rpm -Vp /usr/src/redhat/RPMS/i386/jikes-1.17-1.i386.rpm
Spec 文件时包含 RPM 指令的文本文件。这些指令使用标记名、冒号和值的简单语法:TagName: value
,且标记名称不区分大小写。例如:
Version: 1.15
除指令语法外,还可使用 %define
方式定义 RPM 宏。例如:
%define major 2
定义宏后,可以使用 %{macro_name}
的方式来访问宏,例如
source: %{name}-%{version}.tar.gz
注释以 #
开头,RPM 将忽略注释行。
注释行中应避免使用 %
,例如: # Added new commands to %prep
将会报错,如果一定要这样使用,可以用 %%
,例如:# Added new commands to %%prep
。
在构建 RPM 时,创建的 spec 文件应存储在 SPECS目录中(可以将 spec 文件永久存储在所需的任何位置)。
包描述信息:
Name: myapp
Version: 1.1.2
Release: 1
Epoch: 3
Serial: 6
Group: System Environment/Shells
Distribution: Red Hat Linux
Vendor: The Really Cool Company
URL: http://mycompany.yow/products/coolstuff
Packager: Bob Marley
Copyright: BSD
# Copyright 已经启用,请使用 License
License: LGPL
# Summary:可设置一行,不超过 50 个字符
Summary: A program that does exactly what you want
# 若要添加任意多行描述,请使用 %description,可以输出空行、制表符和其它有限数量格式
%description
This is a really cool package. It contains the really cool
program that provides a maximum return on investment,
or ROI, for achieving your crucial business objectives
utilizing world-class high-caliber componentized software
implemented with world-class quality and performance
metrics.
Spec 文件可以声明一个包可以在多个操作系统上运行,或者绑定到特定操作系统的特定版本。
# ExcludeArch:指令声明包不应该构建在给定的一个或多个体系结构上
ExcludeArch: sparc s390 s390x
# Exclusivearch:指令声明包只能在给定的一个或多个体系结构上构建
ExclusiveArch: i386 ia64 alpha
# Excludeos:指令限制在该操作系统上构建
Excludeos: windows
# ExclusiveOS:指令仅命名可以在其上构建包的一个或多个操作系统
Exclusiveos: linux
设置生成位置
Buildroot: %{_tmppath}/%{name}-%{version}-root
以使用 rpmbuild 命令的 --buildroot 命令行参数覆盖 Buildroot。
命名源文件
大多数包都有一个或多个源代码包,需要在规范文件中命名它们。在大多数情况下,您将拥有源文件的 tar 压缩文件。这些文件可能是自己开发的文件,也可能是从 Internet 站点下载的文件。可以定义一个或多个源标签,从0开始计数。例如:
Source0: telnet-client.tar.gz
Source1: telnet-xinetd
Source2: telnet.wmconfig
如果您只有一条Source指令,则可以跳过0。例如:
Source: telnet-client.tar.gz
还可以使用FTP或HTTP URL来命名源(源指令中列出的 URL 仅供方便和将来参考。RPM不会下载这些文件)。例如:
Source0: ftp://ftp.somesite.yow/pub/linux/%{telnet_version}.tar.gz
将某些源排除在源RPM之外,此示例表示第一个源项不应包含在包中:
NoSource: 0
NoPatch 指令的工作原理与 NoSource 类似,不要在任何给定的 NoSource 或 NoPatch 指令上放置多个数字。
命名补丁程序
补丁的命名类似于源代码,使用类似的语法。例如:
Patch1: telnet-client-cvs.patch
Patch2: telnetd-0.17.diff
Patch3: telnet-0.17-env.patch
Patch4: telnet-0.17-issue.patch
Patch5: telnet-0.17-sa-01-49.patch
Patch6: telnet-0.17-env-5x.patch
Patch10: telnet-0.17-pek.patch
%files 部分包含 RPM 应该从软件包安装的所有文件的列表。该列表应该是详尽的,以便 RPM 系统确切地知道您的软件包安装了什么。不过,有一些选项可以命名一个目录中的所有文件,以帮助处理包含数百个文件的包。
%files
/usr/X11R6/bin/xtoolwait
/usr/X11R6/man/man1/xtoolwait.1
可以使用通配符,可以包含文件夹(但不要直接使用系统目录):
%files
/usr/X11R6/bin/xtoolwait
/usr/X11R6/man/man1/xtoolwait.*
%dir /etc/xtoolwait
也可将文件标记为文档或者配置文件:
%files
/usr/X11R6/bin/xtoolwait
%doc /usr/X11R6/man/man1/xtoolwait.*
# %doc 指定的文件不存在,将会自动创建,如:%doc README NEWS
# %docdir 将保存文档目录和该目录下的所有文件,并标记为文档
%docdir /usr/X11R6/man/man1
# 标记为配置文件
%config /etc/yp.conf
# noreplace:本地文件已经修改,将不会覆盖本地配置文件,若本地文件未修改,则覆盖本地文件
# missingok:意味着在本地磁盘上文件可以不存在
%config(noreplace) /etc/yp.conf
%config(missingok) /etc/md.conf
# %ghost 指定文件不应该存在 RPM 包中
# %attr(mode, user, group) filename
%attr(0644, root, root) /etc/yp.conf
%attr(-, root, -) /etc/yp.conf
%config %attr(-, root, -) /etc/yp.conf
%attr(0700 root root) %dir /var/tux
# %defattr 设置包照中所有文件默认属性
%files
%defattr(-,root,root)
/usr/X11R6/bin/xtoolwait
/usr/X11R6/man/man1/xtoolwait.*
# %lang 标记特定语言的文件
%files
%defattr(-,root,root)
%doc FAQ Fixes NewThings complete.tcsh eight-bit.txt tcsh.html
%{_bindir}/tcsh
%{_bindir}/csh
%{_mandir}/*/*
%lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*
%lang(el) %{_datadir}/locale/el/LC_MESSAGES/tcsh*
%lang(en) %{_datadir}/locale/en/LC_MESSAGES/tcsh*
%lang(es) %{_datadir}/locale/es/LC_MESSAGES/tcsh*
%lang(et) %{_datadir}/locale/et/LC_MESSAGES/tcsh*
%lang(fi) %{_datadir}/locale/fi/LC_MESSAGES/tcsh*
%lang(fr) %{_datadir}/locale/fr/LC_MESSAGES/tcsh*
%lang(it) %{_datadir}/locale/it/LC_MESSAGES/tcsh*
%lang(ja) %{_datadir}/locale/ja/LC_MESSAGES/tcsh*
%lang(pl) %{_datadir}/locale/pl/LC_MESSAGES/tcsh*
%lang(ru) %{_datadir}/locale/ru/LC_MESSAGES/tcsh*
%lang(uk) %{_datadir}/locale/uk/LC_MESSAGES/tcsh*
# %pre 安装之前运行脚本
%pre
# %post 安装之后运行脚本
%post
/sbin/chkconfig --add ypbind
# %preun 卸载之前运行脚本
%preun
if [ "$1" = 0 ] ; then
/sbin/service ypbind stop > /dev/null 2>&1
/sbin/chkconfig --del ypbind
fi
exit 0
# %postun 卸载之后运行脚本
%postun
if [ "$1" -ge 1 ]; then
/sbin/service ypbind condrestart > /dev/null 2>&1
fi
exit 0
命名依赖项
# 基本语法
Requires: capability
Provides: capability
Obsoletes: capability
Conflicts: capability
设置必备条件
# 基本语法
PreReq: capability
PreReq: capability >= version
命名生成依赖项
# RPM 允许使用以下指令在规 spec 文件中定义构建时依赖关系:
BuildRequires:
BuildConflicts:
BuildPreReq:
自动生成依赖项
RPM 默认会自动生成包依赖关系。
触发器为一个软件包提供了一种在另一个软件包的安装状态更改时执行操作的方法。触发器是在 RPM 系统运行的软件包规范文件中定义的脚本。当另一个命名包的状态更改时。如果您的包在某种程度上依赖于另一个包,则触发器可以允许您的包处理对另一个包的更改。
%triggerin -- tcsh
script commands...
此示例为 tcsh 包设置触发器。如果安装或升级了tcsh包,rpm将运行该脚本。如果您的软件包已安装或升级,并且tcsh软件包当前已安装,则RPM也将运行该脚本。
RPM 自动处理包验证,检查是否安装了正确的文件,并测试文件本身是否具有正确的大小和其他属性。当然也可以创建自己的验证脚本,并在 spec 文件中添加如下配置:
%verifyscript
your script commands ....
一个 spec 文件可以定义多个包,这种类型的附加包称为子包。将大型文档集拆分到单独的子包中也很常见。
使用子包,您可以获得:
在大多数情况下,创建子程序包只是作为将程序包生成的文件划分为单独程序包的一种方式。
在 spec 文件中定义子程序包:
%package sub_package_name
# %package -n 可以指定子包的命名方式,默认情况下,子包的名称将是包名、破折号和%Package 指令提供的子包名称
%package -n new_sub_package_name
可重定位的软件包允许用户指定安装软件包的位置。例如,如果您为 Red Hat Linux 构建一个包,则二进制可执行程序的正常目录是 /usr/bin。不过,其他版本的Linux 可能会将可执行程序放入 /opt/bin 中。如果您的软件包强制使用 /usr/bin,那么您的软件包将不能在这些其他系统上工作。
要设置可重定位软件包,需要:
步骤:
设置前缀
Prefix: /usr
以定义多个 prefix:指令,以列出多个顶级目录:
Prefix: /usr
Prefix: /etc
设置文件 section
在 spec 文件中使用 prefix:指令时,%file 部分中的所有文件必须位于以前缀 prefix:指令命名的目录下。
Prefix: /usr
...
%files
%defattr(-,root,root)
/usr/bin/jikes
%doc /usr/doc/jikes-%{version}/license.htm
%doc /usr/man/man1/jikes.1*
并不是所有的软件包都能像可重定位的软件包一样正常工作。有些软件包的文件必须放到某个位置,因此不能重定位。某些软件包的程序被硬编码为在特定位置查找文件,因此无法重新定位到其他位置。其他软件包的符号链接也可能是不可重定位的。此外,您的软件包可能会提供已知目录中其他软件包引用的软件。重新定位这样的软件包将禁用其他软件包,您可能甚至不知道这些软件包。如果您的包面临这些问题中的任何一个,很可能将包设置为可重定位不是一个好主意。
yum -y install gcc gcc-c++
yum -y install make
yum -y install pam pam-devel
yum -y install zlib zlib-devel
yum -y install openssl openssl-devel
yum -y install perl pcre-devel
yum -y install rpm-build
mkdir -p /root/rpmbuild/{BUILD, BUILDROOT, RPMS, SOURCES, SPECS, SRPMS}
将 openssh-8.4p1.tar.gz 放入到 /home/workspace/rpmbuild/SOURCES 目录:
[ft@bogon SOURCES]$ pwd
/root/rpmbuild/SOURCES
[ft@bogon SOURCES]$ wget https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-8.4p1.tar.gz
[ft@bogon SOURCES]$ wget http://ftp.riken.jp/Linux/momonga/6/Everything/SOURCES/x11-ssh-askpass-1.2.4.1.tar.gz
[ft@bogon SOURCES]$ ls
openssh-8.4p1.tar.gz x11-ssh-askpass-1.2.4.1.tar.gz
创建 sepc 文件
cd /root/rpmbuild/SOURCES
tar -zxvf openssh-8.4p1.tar.gz
cp openssh-8.4p1/contrib/redhat/openssh.spec /root/rpmbuild/SPECS
注意:
CentOS 一定要在 /root/rpmbuild 目录下。
修改 spec 文件
修改 askpass 相关配置
cd /root/rpmbuild/SPECS
sed -i -e "s/%global no_gnome_askpass 0/%global no_gnome_askpass 1/g" openssh.spec
sed -i -e "s/%global no_x11_askpass 0/%global no_x11_askpass 1/g" openssh.spec
命令执行完成后,openssh.spec 文件下列配置项将修改为 1:
# Do we want to disable building of x11-askpass? (1=yes 0=no)
%global no_x11_askpass 1
# Do we want to disable building of gnome-askpass? (1=yes 0=no)
%global no_gnome_askpass 1
说明:
8.3 以上版本的 openssh 使用 %global 定义变量,替换之前的 %define。若使用低版本的 openssh,请将上面命令中的 %global 替换为 %define,后者可以直接打开 openssh.spec 文件,编辑 no_x11_askpass 和 no_gnome_askpass 配置项。
取消 openssl 依赖
注释掉 BuildRequires: openssl-devel < 1.1
选项,解除其依赖(在 openssh.spec 文件的第 103 行)。
%if %{compat_openssl}
BuildRequires: compat-openssl10-devel
%else
BuildRequires: openssl-devel >= 1.0.1
#BuildRequires: openssl-devel < 1.1
%endif
配置 openssl 路径(可选)
若需要使用自定义编译的 openssl,可在 openssh.spec 文件的 %configure 部分添加 --with-ssl-dir=/opt/openssl
,其中 /opt/openssl 是 openssl 的安装路径,根据实际情况赋值:
%configure \
--sysconfdir=%{_sysconfdir}/ssh \
--libexecdir=%{_libexecdir}/openssh \
--datadir=%{_datadir}/openssh \
--with-default-path=/usr/local/bin:/bin:/usr/bin \
--with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \
--with-privsep-path=%{_var}/empty/sshd \
--with-ssl-dir=/opt/openssl \
--with-md5-passwords \
--mandir=%{_mandir} \
--with-mantype=man \
--disable-strip \
cd /root/rpmbuild/SPECS
rpmbuild -ba openssh.spec
注意:
实际执行还是使用了 root 用户,并不像前面的章节建议使用非 root 用户。
构建完成后,在 /root/rpmbuild/RPMS/x86_64 目录下会生成二进制 RPM 包:
[root@bogon x86_64]# ls
openssh-8.4p1-1.el7.x86_64.rpm
openssh-clients-8.4p1-1.el7.x86_64.rpm
openssh-debuginfo-8.4p1-1.el7.x86_64.rpm
openssh-server-8.4p1-1.el7.x86_64.rpm
在 /root/rpmbuild/SRPMS 目录下会生成源码包:
[root@bogon SRPMS]# ls
openssh-8.4p1-1.el7.src.rpm
将打包好的 openssh 二进制安装包拷贝到需要 SSH 远程访问的机器,执行安装命令:
rpm -Uvh openssh-* --nodeps
下一节内容将详细讲解安装 OpenSSH 8.4
[ft@bogon ~]$ cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
[ft@bogon ~]$ uname -a
Linux bogon 3.10.0-1160.15.2.el7.x86_64 #1 SMP Wed Feb 3 15:06:38 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
[ft@bogon ~]$ ssh -V
OpenSSH_7.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
注意:
卸载自带 SSH 组件前建议先备份 /etc/ssh/sshd_config 、/etc/ssh/ssh_config 和 /etc/pam.d/sshd 文件。
# 查看系统当前 openssh 组件
[root@bogon ~]# rpm -qa | grep openssh
openssh-clients-7.4p1-21.el7.x86_64
openssh-server-7.4p1-21.el7.x86_64
openssh-7.4p1-21.el7.x86_64
# 停止 sshd 服务
[root@bogon ~]# systemctl stop sshd
# 卸载系统 SSH 组件
[root@bogon ~]# rpm -e `rpm -qa | grep openssh` --nodeps
# 查看系统当前 openssh 组件,若输出为空,则卸载成功
[root@bogon ~]# rpm -qa | grep openssh
# 准备 OpenSSH 8.4 RPM 安装包
[root@bogon openssh]# ls
openssh-8.4p1-1.el7.x86_64.rpm openssh-debuginfo-8.4p1-1.el7.x86_64.rpm
openssh-clients-8.4p1-1.el7.x86_64.rpm openssh-server-8.4p1-1.el7.x86_64.rpm
# 安装 OpenSSH 8.4
[root@bogon openssh]# rpm -Uvh openssh-* --nodeps
Preparing... ################################# [100%]
Updating / installing...
1:openssh-8.4p1-1.el7 ################################# [ 25%]
2:openssh-clients-8.4p1-1.el7 ################################# [ 50%]
3:openssh-server-8.4p1-1.el7 ################################# [ 75%]
4:openssh-debuginfo-8.4p1-1.el7 ################################# [100%]
# 查看安装后的组件
[root@bogon openssh]# rpm -qa | grep openssh
openssh-debuginfo-8.4p1-1.el7.x86_64
openssh-server-8.4p1-1.el7.x86_64
openssh-8.4p1-1.el7.x86_64
openssh-clients-8.4p1-1.el7.x86_64
# 查看 SSH 版本
[root@bogon openssh]# ssh -V
OpenSSH_8.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
修改 /etc/ssh/sshd_config 文件中的下列配置项为 yes:
PasswordAuthentication yes
PermitRootLogin yes
UsePAM yes
若已经提前备份 /etc/ssh/sshd_config 文件,在这里替换回原文件即可。
修改 /etc/pam.d/sshd 配置文件内容,使得它的配置和原先一致(如果已经备份该文件,在这里替换回原文件即可):
#%PAM-1.0
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
# Used with polkit to reauthorize users in remote sessions
-auth optional pam_reauthorize.so prepare
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include password-auth
session include postlogin
# Used with polkit to reauthorize users in remote sessions
-session optional pam_reauthorize.so prepare
[root@bogon ssh]# systemctl restart sshd
[root@bogon ssh]# systemctl status sshd
● sshd.service - SYSV: OpenSSH server daemon
Loaded: loaded (/etc/rc.d/init.d/sshd; bad; vendor preset: enabled)
Active: active (running) since Wed 2021-03-03 19:41:48 PST; 3s ago
Docs: man:systemd-sysv-generator(8)
Process: 4678 ExecStop=/etc/rc.d/init.d/sshd stop (code=exited, status=0/SUCCESS)
Process: 4686 ExecStart=/etc/rc.d/init.d/sshd start (code=exited, status=0/SUCCESS)
Main PID: 4696 (sshd)
Tasks: 1
CGroup: /system.slice/sshd.service
└─4696 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups
Mar 03 19:41:48 bogon systemd[1]: Starting SYSV: OpenSSH server daemon...
Mar 03 19:41:48 bogon sshd[4696]: Server listening on 0.0.0.0 port 22.
Mar 03 19:41:48 bogon sshd[4686]: Starting sshd:[ OK ]
Mar 03 19:41:48 bogon sshd[4696]: Server listening on :: port 22.
Mar 03 19:41:48 bogon systemd[1]: Started SYSV: OpenSSH server daemon.
注意:
重启 SSH 服务,可能遇到下面的问题:
[root@bogon ~]# service sshd restart Restarting sshd (via systemctl): Job for sshd.service failed because the control process exited with error code. See "systemctl status sshd.service" and "journalctl -xe" for details. # 根据提示执行 systemctl status sshd.service 查看问题 [root@bogon ~]# systemctl status sshd.service ● sshd.service - SYSV: OpenSSH server daemon Loaded: loaded (/etc/rc.d/init.d/sshd; bad; vendor preset: enabled) Active: failed (Result: exit-code) since Wed 2021-03-03 19:22:44 PST; 1min 37s ago Docs: man:systemd-sysv-generator(8) Process: 4219 ExecStart=/etc/rc.d/init.d/sshd start (code=exited, status=1/FAILURE) Mar 03 19:22:44 bogon sshd[4219]: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ Mar 03 19:22:44 bogon sshd[4219]: Permissions 0640 for '/etc/ssh/ssh_host_ed25519_key' are too open. Mar 03 19:22:44 bogon sshd[4219]: It is required that your private key files are NOT accessible by others. Mar 03 19:22:44 bogon sshd[4219]: This private key will be ignored. Mar 03 19:22:44 bogon sshd[4219]: sshd: no hostkeys available -- exiting. Mar 03 19:22:44 bogon sshd[4219]: [FAILED] Mar 03 19:22:44 bogon systemd[1]: sshd.service: control process exited, code=exited status=1 Mar 03 19:22:44 bogon systemd[1]: Failed to start SYSV: OpenSSH server daemon. Mar 03 19:22:44 bogon systemd[1]: Unit sshd.service entered failed state. Mar 03 19:22:44 bogon systemd[1]: sshd.service failed.
解决方法:
根据提示信息,/etc/ssh/ssh_host_ed25519_key 文件权限有问题,我们可以尝试修改其权限。
[root@bogon ~]# cd /etc/ssh/ [root@bogon ssh]# ls -l total 608 -rw-------. 1 root root 577834 Mar 3 01:44 moduli -rw-r--r--. 1 root root 1531 Mar 3 01:44 ssh_config -rw-------. 1 root root 3148 Mar 3 19:10 sshd_config -rw-------. 1 root root 1369 Mar 3 19:21 ssh_host_dsa_key -rw-r--r--. 1 root root 600 Mar 3 19:21 ssh_host_dsa_key.pub -rw-r-----. 1 root ssh_keys 227 Feb 24 18:54 ssh_host_ecdsa_key -rw-r--r--. 1 root root 162 Feb 24 18:54 ssh_host_ecdsa_key.pub -rw-r-----. 1 root ssh_keys 387 Feb 24 18:54 ssh_host_ed25519_key -rw-r--r--. 1 root root 82 Feb 24 18:54 ssh_host_ed25519_key.pub -rw-r-----. 1 root ssh_keys 1679 Feb 24 18:54 ssh_host_rsa_key -rw-r--r--. 1 root root 382 Feb 24 18:54 ssh_host_rsa_key.pub [root@bogon ssh]# chmod 600 ssh_host_ed25519_key [root@bogon ssh]# chmod 600 ssh_host_ecdsa_key [root@bogon ssh]# chmod 600 ssh_host_rsa_key
然后重启 SSH 服务。
# 首次连接可能需要执行 ssh-keygen -R <目标主机 IP>
C:\Users\Sunny>ssh-keygen -R 192.168.16.22
# Host 192.168.16.22 found: line 5
C:\Users\Sunny/.ssh/known_hosts updated.
Original contents retained as C:\Users\Sunny/.ssh/known_hosts.old
# 远程连接
C:\Users\Sunny>ssh [email protected]
The authenticity of host '192.168.16.22 (192.168.16.22)' can't be established.
ECDSA key fingerprint is SHA256:F0ATU27wYShI3KpIqbuDv+DH9sTMUkfvfFBWpmy6Hsk.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.16.22' (ECDSA) to the list of known hosts.
Password:
Last login: Wed Mar 3 19:22:23 2021
[root@bogon ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
[root@bogon ~]# ssh -V
OpenSSH_8.4p1, OpenSSL 1.0.2k-fips 26 Jan 2017
[root@bogon ~]# exit
logout
Connection to 192.168.16.22 closed.
C:\Users\Sunny>
安装自定义的 PAM 模块,然后在 /etc/pam.d/sshd 配置文件添加自定义的 PAM 模块:
#%PAM-1.0
# 自定义 PMA 模块 pam_otp.so
auth required pam_otp.so
# ---------------------------------------------------------------
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
# Used with polkit to reauthorize users in remote sessions
-auth optional pam_reauthorize.so prepare
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include password-auth
session include postlogin
# Used with polkit to reauthorize users in remote sessions
-session optional pam_reauthorize.so prepare
SSH 连接测试:
C:\Users\Sunny>ssh [email protected]
Password:
[1] Send Msg [2] Push Phone
[3] Auth OTP [4] Exit
choose verification mode(1/2/3/4):3
PassCode:
Last login: Wed Mar 3 19:57:41 2021 from 192.168.16.70
[ft@bogon ~]$ cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
[ft@bogon ~]$ exit
logout
Connection to 192.168.16.22 closed.
C:\Users\Sunny>
OpenSSH 8.4 RPM 下载链接:https://download.csdn.net/download/wzfgd/15561299