Linux Software Management

  • Linux 软件包管理安装。

参考书目/链接

软件包

Windows

  • 开始介绍 Linux 软件包之前,先大致回忆一下 Windows 场景下的我们常常使用的软件包形态。
  • Win 环境下:
    • 大量的软件应用程序都是使用诸如 .exe/.msi 等类型的文件进行安装,直接运行该安装程序,按照步骤勾选相应的可选配置就能安装对应的软件。
      • MSI 就是 microsoft installer 的简写,msi 文件就是 window installer 的数据包,把所有和安装文件相关的内容封装在一个包里。
      • exe 是一个安装引导程序。主要是用于检查安装的环境,当检查成功后,会自动再安装 msi 文件。
    • 除了安装程序以外,常常还有一些压缩包的形式来安装软件(也就是所谓的绿色版),本质就是把程序的全部数据以及依赖的环境给压缩到一个文件夹中,而下载该文件夹就可以直接执行其中保存的可执行程序。
20210225220304

Linux

  • 大多数现代类 Unix 操作系统都提供了一个集中的软件包管理机制,以帮助用户搜索、安装和管理软件。而软件通常以「包」的形式存储在仓库「repository」中,对软件包的使用和管理被称为包管理。
  • Linux 包的基本组成部分通常有:共享库、应用程序、服务和文档。
  • Linux 软件包分类:
    • 源码包
    • 二进制包(RPM/DEB包)
    • yum/apt 源在线安装
    • 脚本安装包(本质还是源码包和二进制包)

Linux 软件包管理

软件包管理系统

  • 大多数包管理系统是建立在包文件上的集合,包文件通常包含编译好的二进制文件和其它资源组成的:软件、安装脚本、元数据及其所需的依赖列表。
  • 因为 Linux 有很多发行版,各自的管理系统也有一定的差异
系统 格式 工具
Debian .deb apt, apt-cache、apt-get、dpkg
Ubuntu .deb apt、apt-cache、apt-get、dpkg
CentOS .rpm yum
Fedora .rpm dnf
  • Debian 及其衍生产品如:Ubuntu、Linux Mint 和 Raspbian 的包格式为.deb文件,APT 是最常见包操作命令,可:搜索库、安装包及其依赖和管理升级。而要直接安装现成.deb包时需要使用dpkg命令。
  • CentOS、Fedora 及 Red Hat 系列 Linux 使用RPM包文件,并使用yum命令管理包文件及与软件库交互。在最新的 Fedora 版本中,yum命令已被dnf取代进行包管理。

常见操作

  • 更新本地包数据库列表:
    • apt-get update
    • yum check-update
    • dnf check-update
  • 升级已安装的包:
    • apt-get upgrade
    • apt-get dist-upgrade
    • yum update /dnf upgrade
  • 查找/搜索软件包:
    • apt-cache search xxx
    • yum search xxx
    • yum search all xxx
    • dnf search xxx
    • dnf search all xxx
  • 查看某个软件包信息:
    • apt-cache show [pkg_name]
    • dpkg -s [pkg_name] (显示包的安装状态)
    • yum info [pkg_name]
    • yum deplist [pkg_name] (列出包的依赖)
    • dnf info [pkg_name]
    • dnf repoquery –requires [pkg_name]
  • 安装包:
    • apt-get install xxx
    • yum instal xxx
    • dnf install xxx
  • 移除包:
    • apt-get remove xxx
    • apt-get autoremove (自动移除已知不需要的包)
    • yum remove xxx
    • dnf erase xxx

本地文件系统安装

  • 首先简要介绍本地安装软件包的场景和主要命令,然后以 RPM 为例详细说明。

从本地文件系统直接安装包

  • 很多时候,我们在进行测试或从某个地方直接拿到软件包之后需要从本地文件系统直接安装包。(特别是针对一些无公网的环境,无法直接使用包管理工具直接安装相关依赖)
  • Debian 及衍生系统可以使用 dpkg 进行安装,CentOS 和 Fedora 系统使用 yum 和 dnf 命令进行安装。
本地安装命令
  • dpkg -i [pkg_name].deb
  • apt-get install -y gdebi&& sudo gdebi [pkg_name].deb (使用gdebi检索缺少的依赖关系)
  • yum install [pkg_name].rpm
  • dnf install [pkg_name].rpm

RPM

  • RPM命名“RedHat Package Manager”,简称则为RPM。这个机制最早由Red Hat这家公司开发出来的,后来实在很好用,因此很多distributons就使用这个机制来作为软件安装的管理方式,包括Fedora,CentOS,SuSE等知名的开发商都是用它。
  • RPM最大的特点就是需要安装的软件已经编译过,并已经打包成RPM机制的安装包,通过里头默认的数据库记录这个软件安装时需要的依赖软件。当安装在你的Linux主机时,RPM会先依照软件里头的数据查询Linux主机的依赖属性软件是否满足,若满足则予以安装,若不满足则不予安装。

构建流程

要构建 RPM,必须:

  • 依照 rpmbuild 规范设定一个目录结构。
  • 将源代码和附带文件放在目录中合适的位置。
  • 创建 spec 文件。
  • 编译 RPM。可以选择编译源 RPM,以与其他人共享您的源代码。
目录结构
  • BUILD。BUILD 用作实际编译软件的暂存空间。
  • RPMS。RPMS 包含 rpmbuild 所编译的二进制 RPM。
  • SOURCES。SOURCES 存储源代码。
  • SPECS。SPECS 包含您的 spec 文件,您想要构建的一个 RPM 对应一个 spec 文件。
  • SRPMS。SRPMS 包含在这个过程中构建的源 RPM。
20210226153713
准备文件
  • step1. 将源代码(理想情况下应捆绑为一个 tarball 压缩文件)复制到 SOURCES 目录
  • step2. 创建 spec 文件。spec 文件只是一个具有特殊语法的文本文件。
    • 此处举一个简单例子 wget 打包
# This is a sample spec file for wget

# 定义了五个变量 
%define _topdir     /home/strike/mywget
%define name            wget 
%define release     1
%define version     1.12
%define buildroot %{_topdir}/%{name}-%{version}-root
 
# 设置若干关键参数
BuildRoot:  %{buildroot}
Summary:        GNU wget
License:        GPL
Name:           %{name}
Version:        %{version}
Release:        %{release}
Source:         %{name}-%{version}.tar.gz
Prefix:         /usr
Group:          Development/Tools

# 简单明了地描述软件。这一行将在用户运行 rpm -qi 来查询 RPM 数据库时显示。您可以说明包的用途,描述任何警告或额外的配置说明等。
%description
The GNU wget program downloads files from the Internet using the command-line.

# 生成一个 shell 脚本,该脚本嵌入到 RPM 中,随后作为安装的一部分运行
# 准备源代码
# %setup -q 是一个 %prep 宏,用于自动解压 Source 中的特定 tarball 压缩文件
%prep
%setup -q

# 生成一个 shell 脚本,该脚本嵌入到 RPM 中,随后作为安装的一部分运行
# 手动配置和启动构建过程的步骤 
%build
./configure
make

# 生成一个 shell 脚本,该脚本嵌入到 RPM 中,随后作为安装的一部分运行
%install
make install prefix=$RPM_BUILD_ROOT/usr

# 列出应该捆绑到 RPM 中的文件,还可以设置权限和其他信息。
%files
%defattr(-,root,root)
/usr/local/bin/wget

# %doc 告诉 RPM 该文件为一个文档文件,所以如果用户使用 --excludedocs 安装包,将不会安装该文件。
%doc %attr(0444,root,root) /usr/local/share/man/man1/wget.1
  • 再来看 tcmu-runner.spec 的例子
%global _hardened_build 1

# 运行 rpmbuild 时读取的一些条件参数
# without rbd dependency
# if you wish to exclude rbd handlers in RPM, use below command
# rpmbuild -ta @PACKAGE_NAME@-@[email protected] --without rbd
%bcond_without rbd

# without glusterfs dependency
# if you wish to exclude glfs handlers in RPM, use below command
# rpmbuild -ta @PACKAGE_NAME@-@[email protected] --without glfs
%bcond_without glfs

# without qcow dependency
# if you wish to exclude qcow handlers in RPM, use below command
# rpmbuild -ta @PACKAGE_NAME@-@[email protected] --without qcow
%bcond_without qcow

# without zbc dependency
# if you wish to exclude zbc handlers in RPM, use below command
# rpmbuild -ta @PACKAGE_NAME@-@[email protected] --without zbc
%bcond_without zbc

# without file backed optical dependency
# if you wish to exclude fbo handlers in RPM, use below command
# rpmbuild -ta @PACKAGE_NAME@-@[email protected] --without fbo
%bcond_without fbo

# without tcmalloc dependency
# if you wish to exclude tcmalloc, use below command
# rpmbuild -ta @PACKAGE_NAME@-@[email protected] --without tcmalloc
%bcond_without tcmalloc

# 设置若干关键参数
Name:          tcmu-runner
Summary:       A daemon that handles the userspace side of the LIO TCM-User backstore
Group:         System Environment/Daemons
License:       ASL 2.0 or LGPLv2+
Version:       1.0
URL:           https://github.com/open-iscsi/tcmu-runner

Release:       0%{dist}
BuildRoot:     %(mktemp -udp %{_tmppath}/%{name}-%{version})
Source:       %{name}-%{version}.tar.gz
ExclusiveOS:   Linux

BuildRequires: cmake make gcc
BuildRequires: libnl3-devel glib2-devel zlib-devel kmod-devel

# 针对不同条件参数下的依赖处理
%if %{with rbd}
BuildRequires: librbd1-devel librados2-devel
Requires(pre): librados2, librbd1
%endif

%if %{with glfs}
BuildRequires: glusterfs-api-devel
Requires(pre): glusterfs-api
%endif

%if %{with tcmalloc}
BuildRequires: gperftools-devel
Requires:      gperftools-libs
%endif

# 基本依赖
Requires(pre): kmod, zlib, libnl3, glib2, logrotate, rsyslog
Requires:      libtcmu = %{version}-%{release}

# 软件描述
%description
A daemon that handles the userspace side of the LIO TCM-User backstore.

LIO is the SCSI target in the Linux kernel. It is entirely kernel code, and
allows exported SCSI logical units (LUNs) to be backed by regular files or
block devices. But, if we want to get fancier with the capabilities of the
device we're emulating, the kernel is not necessarily the right place. While
there are userspace libraries for compression, encryption, and clustered
storage solutions like Ceph or Gluster, these are not accessible from the
kernel.

The TCMU userspace-passthrough backstore allows a userspace process to handle
requests to a LUN. But since the kernel-user interface that TCMU provides
must be fast and flexible, it is complex enough that we'd like to avoid each
userspace handler having to write boilerplate code.

tcmu-runner handles the messy details of the TCMU interface -- UIO, netlink,
pthreads, and DBus -- and exports a more friendly C plugin module API. Modules
using this API are called "TCMU handlers". Handler authors can write code just
to handle the SCSI commands as desired, and can also link with whatever
userspace libraries they like.

# 生成的 RPM 包 libtcmu
%package -n libtcmu
Summary:       A library supporting LIO TCM-User backstores processing
Group:         Development/Libraries

%description -n libtcmu
libtcmu provides a library for processing SCSI commands exposed by the
LIO kernel target's TCM-User backend.

# 生成的 RPM 包 libtcmu-devel
%package -n libtcmu-devel
Summary:       Development headers for libtcmu
Group:         Development/Libraries
Requires:      %{name} = %{version}-%{release}
Requires:      libtcmu = %{version}-%{release}

%description -n libtcmu-devel
Development header(s) for developing against libtcmu.

%global debug_package %{nil}

# 准备源代码
%prep
%setup -n %{name}-%{version}

# 手动配置和启动构建
%build
%{__cmake} \
 -DSUPPORT_SYSTEMD=ON -DCMAKE_INSTALL_PREFIX=%{_usr} \
 %{?_without_rbd:-Dwith-rbd=false} \
 %{?_without_zbc:-Dwith-zbc=false} \
 %{?_without_qcow:-Dwith-qcow=false} \
 %{?_without_glfs:-Dwith-glfs=false} \
 %{?_without_fbo:-Dwith-fbo=false} \
 %{?_without_tcmalloc:-Dwith-tcmalloc=false} \
 .
%{__make}

%install
%{__make} DESTDIR=%{buildroot} install
%{__rm} -f %{buildroot}/etc/tcmu/tcmu.conf.old
%{__rm} -f %{buildroot}/etc/logrotate.d/tcmu-runner.bak/tcmu-runner

# 列出应该捆绑到 RPM 中的文件
%files
%{_bindir}/tcmu-runner
%dir %{_sysconfdir}/dbus-1/
%dir %{_sysconfdir}/dbus-1/system.d
%config %{_sysconfdir}/dbus-1/system.d/tcmu-runner.conf
%dir %{_datadir}/dbus-1/
%dir %{_datadir}/dbus-1/system-services/
%{_datadir}/dbus-1/system-services/org.kernel.TCMUService1.service
%{_unitdir}/tcmu-runner.service
%dir %{_libdir}/tcmu-runner/
%{_libdir}/tcmu-runner/*.so
%{_mandir}/man8/*
%doc README.md LICENSE.LGPLv2.1 LICENSE.Apache2
%dir %{_sysconfdir}/tcmu/
%config %{_sysconfdir}/tcmu/tcmu.conf
%config(noreplace) %{_sysconfdir}/logrotate.d/tcmu-runner
%ghost %attr(0644,-,-) %{_sysconfdir}/tcmu/tcmu.conf.old
%ghost %attr(0644,-,-) %{_sysconfdir}/logrotate.d/tcmu-runner.bak/tcmu-runner

%files -n libtcmu
%{_libdir}/libtcmu*.so.*

%files -n libtcmu-devel
%{_libdir}/libtcmu*.so

构建 RPM
  • 例如构建 wget:

rpmbuild -v -bb --clean SPECS/wget.spec

此命令使用指定的 spec 文件构建一个二进制包(-bb 表示 “构建二进制包”),还会生成详细的输出(-v)。构建实用程序在生成包之后删除构建树(--clean)。如果还希望构建源 RPM,指定 -ba(“构建所有包”)来代替 -bb。(查看 rpmbuild 清单页面,了解完整的选项列表。)

  • rpmbuild 执行以下步骤:
    • 读取并解析 wget.spec 文件。
    • 运行 %prep 节,将源代码解压到临时目录。在这里,临时目录为 BUILD。
    • 运行 %build 节,编译代码。
    • 运行 %install 节,将代码安装到构建机器上的目录中。
    • 从 %files 节读取文件列表,将它们收集到一起,然后创建一个二进制 RPM(和源 RPM 文件,如果已选择)。

安装流程

20210226151530
  • rpm -ivh package-name
    • -i:install的意思,安装
    • -v:查看更详细的安装信息画面(provide more detailed output)
    • -h:以安装信息栏显示安装进度
错误处理
  • 安装rpm包时提示错误:依赖检测失败: --nodeps --force
[root@localhost ~]# rpm -ivh tcmu-runner-2.0.1-0.el7.x86_64.rpm 
错误:依赖检测失败:
	libhcs_obj_util.so()(64bit) 被 tcmu-runner-2.0.1-0.el7.x86_64 需要

[root@localhost ~]# rpm -ivh tcmu-runner-2.0.1-0.el7.x86_64.rpm --nodeps --force
准备中...                          ################################# [100%]
正在升级/安装...
   1:tcmu-runner-2.0.1-0.el7          ################################# [100%]
[root@localhost ~]# systemctl status tcmu-runner
● tcmu-runner.service - LIO Userspace-passthrough daemon
   Loaded: loaded (/usr/lib/systemd/system/tcmu-runner.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:tcmu-runner(8)