# Linux 发行版
Linux 操作系统 = Linux 内核 + 不同功能
但是因为内核和功能包有多种不同配置,因此 Linux 有多种发行版。
几种主要的发行版及其衍生是:
- Arch -> Manjaro
- Debian -> Ubuntu
- RHEL -> Scientific Linux
# 安装软件的困惑?
我们要在 Linux 操作系统上安装一个软件,思考如下问题:
- 你需要哪些文件?如何获取他们?
- 用户需要做多少工作?
- 开发者需要做多少工作?
- 在发行软件的过程中还有其他人参与工作吗?
- 如何更新软件包?
- 如何保证软件包来源的安全性?
一个简陋的安装方案是:直接下载一堆文件。这其中包含的内容有:
- 编译好的二进制可执行文件
- 配置信息
- 说明文档
- 许可证 (License)
- 其他
那么问题来了:
- 我们需要哪些文件?
- 这些文件放在哪里?
- 如何进行环境配置?
- 这个安装包和我的系统兼容吗?
- 我怎么更新呢?
一个进阶的安装方案是:下载一个压缩包。但是我们也面临一些问题:
- 这里面的文件是编译好的还是未编译的?
- 软件包之间存在依赖关系怎么办?
- 这个软件如何应对不同 Linux 发行版的需求?
- 如何更新?如何保证更新后的版本可靠?
# 解决方案:打包!
# 什么是包?
包是 Linux 操作系统上软件的组织方式。
# 什么是仓库( repository
)?
仓库是一系列软件包的合集列表。 Debian
上常见的仓库包括:
- Debian stable (all the packages available to install on a default Debian stable install)
- Debian security updates
- Debian backports
- Docker’s custom repositories
其中:
- 每个 Linux 发行版都维护仓库,里面列举了该仓库中可安装的所有软件包
- 包维护者负责对开发者的软件进行打包
- 对于不同的 Linux 发行版,打包的方式不同
包和仓库区别的详细解释参考这里:
- what are packages and repositories
-
apt-update
和apt-upgrade
的区别
# 包的安装过程
- 从包列表中读取该包
- 查看该包的所有依赖项
- 看看依赖项中哪些包已经安装了
- 安装未安装的依赖
- 解压缩文件等
- 完成一些安装后需要做的工作,如将其作为
service
启动
# 包更新方式
- 部分 Linux 发行版采用
periodic release
方式,例如Debian
,2 年一发行 - 部分采用
rolling release
方式,例如Arch
,发行版更新更快,但是是以稳定性为代价
更多内容参考这里:Rolling distribution releases versus periodic releases are a tradeoff
# 自动化包管理工具
# apt
apt update
:生成列表,显示仓库中包含哪些包apt upgrade
/apt dist-upgrade
:把列表中的包升级到最新版本apt policy <packagename>
:列举可安装的包版本apt -t [targetrelease] install [package]
:安装特定版本包apt install <packagename>
:安装包apt remove <packagename>
:卸载包apt search <packagename>
:搜索包apt install ./<packagename>.deb
:安装本地的deb
包apt download <packagename>.deb
:下载包几种不同命令的区别参考这里:
- Why use apt-get upgrade instead of apt-get dist-upgrade?
:::
# dpkg
: 多用于安装本地包
dpkg -i [packagefilename]
:安装本地包dpkg --remove [packagename]
:卸载本地包dpkg -I [packagename]
:查看本地包的更多信息dpkg --configure -a
:查看所有解压了但是还没安装的包
# 使用什么包?
在 /etc/apt/sources.list
和 /etc/apt/sources.list.d
文件中维护镜像源:
deb http://mirrors/debian/ stretch-backports main contrib non-free | |
deb http://mirrors/debian-security/ stretch/updates main contrib non-free | |
deb-src http://mirrors/debian-security/ stretch/updates main contrib non-free | |
deb http://mirrors/debian/ stretch-updates main contrib non-free | |
deb-src http://mirrors/debian/ stretch-updates main contrib non-free | |
deb http://mirrors/debian/ stretch main contrib non-free | |
deb-src http://mirrors/debian/ stretch main contrib non-free | |
# OCF | |
deb http://apt/ stretch-backports main | |
deb-src http://apt/ stretch-backports main | |
deb http://apt/ stretch main | |
deb-src http://apt/ stretch main | |
deb http://mirrors/puppetlabs/apt/ stretch puppet |
我个人的理解是, repository
是指仓库名,仓库中列举了该仓库有哪些软件包。而 mirror list
指明了从哪里下载这个仓库中的软件包(网络地址)?在清华的镜像中有这个仓库,而在中科大的镜像中也有这个仓库。镜像中仓库的内容随着官方仓库内容的更新而更新?
关于什么是镜像,请看这里:
- What are mirrors?
不同的仓库中的软件版本可能不同,需要通过 apt policy
来看软件包所属的仓库。
# 每行内容如何解读?
以下内容摘自 UC Berkeley System Admin Decal 原文
deb http://mirrors/debian/ stretch-backports main contrib non-free |
deb
is binary package source.deb-src
indicates src packages.
http://…
describes the location
stretch-backports
means that this is forJessie stretch
and from abackport
repository
main
means that the repo has packages licensed underDebian Free Software Guidelines (DFSG)
contrib
repos have packages licensed underDSFG
but requirenon-free dependencies
non-free
repos have packages that do not comply withDSFG
# 手动安装包
包中通常含有 Makefile
文件,我们可以手动的进行安装。
步骤:
- 安装所需的相关包,例如
gcc
等 ./configure
make
make install
不便之处:卸载麻烦。
# 包结构
Debian 包通常具有如下几个目录和文件:
control
:涵盖包的元信息,例如包的大小、版本、依赖debian-binary
etc
:配置文件md5sums
:文件有效性检验usr
bin
:可执行文件,要加到$PATH
环境变量中share
:文档,man page,本地化设置doc
:文档info
: info pagelocale
:本地化设置man
:man page
# 自己组包
# /usr 目录下几个重要的目录
/usr/bin
二进制可执行文件/usr/lib
相关的库/usr/include
头文件/usr/share
文档等等
# 打包过程:将 hellopenguin.c
程序打包
# 初始准备
- 编写
hellopenguin.c
程序
#include <stdio.h> | |
int main(void) | |
{ | |
printf("Hello Penguin!\n"); | |
return 0; | |
} |
- 编译
hellopenguin.c
程序,生成可执行文件hellopenguin
gcc hellopenguin.c -o hellopenguin |
# 打包环境准备
- 使用
fpm
工具 (Ruby Gem
)
$ sudo apt install ruby-dev | |
$ sudo gem install fpm | |
$ fpm -s dir -t deb -n [name here] -v [version #] -C [the directory with the /usr folder] |
如果 gem
安装 fpm
过慢的话,需要给 ruby 环境换源,命令如下(这里使用清华源):
# 添加镜像源并移除默认源 | |
gem sources --add https://mirrors.tuna.tsinghua.edu.cn/rubygems/ --remove https://rubygems.org/ | |
# 列出已有源 | |
gem sources -l | |
# 应该只有镜像源一个 |
或者在 ~/.gemrc
中将 https://mirrors.tuna.tsinghua.edu.cn/rubygems/
加到 sources
字段。
- 查看
fpm
是否安装,输入fpm
# 创建包文件夹
- 创建目录
packpenguin/usr/bin
,将hellopenguin
放进去
mkdir -p packpenguin/usr/bin | |
mv hellopenguin packpenguin/usr/bin |
- 在
packpenguin
的父目录中,使用fpm
进行打包,命令如下:
fpm -s dir -t deb -n hellopenguin -v 1.0~ocf1 -C packpenguin |
其中几个字段解释如下:
-s
:使用一个目录构建-t
:生成deb
包-n
:输出包的名字叫hellopenguin
-v
:版本号为1.0~ocf1
-C
: 由packpenguin
目录生成
- 安装我们组建的包:
sudo dpkg -i ./hellopenguin_1.0~ocf1_amd64.deb
- 输入
hellopenguin
,运行hellopenguin
,可以看到输出了Hello Penguin!
要卸载我们安装的包,可以使用 dpkg --remove hellopenguin
命令。
# 参考资料
- Packaging
- Advanced Lab 2 - Packages and Packaging and Troubleshooting
- Distros, Packaging, and Compiling
- Beginner Lab 4 - Debian, packages, compiling software
- FPM 文档
- TLDR 页面