linux程序包管理初步
Linux程序包管理
我们linux操作系统从底层到高层的层次结构:
最底层首先是硬件,计算机的计算能力都是在硬件逻辑上设计实现的,而不同厂商生产的芯片哪怕是同一厂商生产的同一型号的芯片,他们给我们提供的计算接口都不一样,我们基本都同说过嵌入式开发,那么这种开发如果没有系统可以使用的话,主要是面向硬件,来写程序的,而这种程序只能适应一种或者几种有限的芯片,单片机尤其如此,现在很多嵌入式开发过程中,也已经有了一种通用层来实现,但是像单片机这种还是面向硬件编程的,
然后在底层之上就是将硬件接口封装起来的操作系统层,系统层将底层的硬件接口封装起来以后,通过系统调用(system call),向上输出,但是系统调用仍然很底层,为了加速开发操作,在操作系统层之上又加了半层叫"库(lib call)",注意这里不是全层,而是半层,因为对于程序员来讲,可以面向半层"库"来写程序,也可以面向我们的操作系统来写程序,然后在库之上就是应用程序了,应用程序是给我们真正带来一些生产力的,我们的内核是不能完成任何具体的操作的,在这众多的应用类型程序中,我们知道有一类比较独特的,他主要是让用户跟主机交互的,叫shell任何利用操作系统完成任务的操作,都是通过应用程序完成的,所以我们说将来我们真正去实现运维操作的过程中,除了系统管理,库调用管理之外,其实作为运维人员来讲,就是不停的在我们的操作系统上安装配置某一应用程序包,然后让这个应用程序包运行起来,并提供服务,或者利用此工具完成某种具体相应操作的过程。那对于我们运维人员来讲,安装卸载管理程序包,是实现很多后期工作的最基础,最根本的任务,所以首先我们要学会灵活实现对于程序包的安装管理操作。
任何程序的运行,他有可能在程序包上提供两种格式的程序包,我们称之为源码包或者叫二进制包,那么我们将到这就不得不回顾一下以前讲到的API和ABI,API叫应用程序开发接口,ABI叫应用程序二进制接口。我们说过,API层次兼容未必ABI层次兼容。因为有些操作系统他们执行程序的格式,或者对二进制的是识别格式,并非是相同的,像linux跟类unix(Unix-like)他们的操作系统,一般而言是相同的,他们的ABI是相同的,但是与windows相差很远,比方说windows系统上的可执行程序都是exe或者是msi的,而linux上的是elf格式的。所以他们在ABI层次不兼容,所以我们说即使我们使用高级编程语言,去编写程序,他们即便是在源码格式兼容的,但是一旦编译成功以后,本来是linux上面的格式的,而跑到windows上一样依然无法运行。所以有一个程序包,在linux上编译好了,他是二进制格式的,我们是不能拿来装到windows之上的。反过来如果一个程序包在windows上编译好了,是一个exe格式的文件,能不能在linux系统上运行起来呢?也很难。我们可以借助虚拟化将二者的差异将其磨平了,比方说现在的各种各样的应用程序,几乎都是针对库调用来开发的,很少说是直接通过系统调用来实现。即使是通过系统调用来实现,那也没问题,现在在windows上有很多程序模拟linux的库,在linux上也有很多模拟windows库的程序。
比方说现在这里有一个linux操作系统,没关系我们装一个WinE,这个wine就能在linux上模拟出windows库来。所以我们就可以借助wine来运行windows应用程序。比方说希望在linux上玩的各种各样的游戏,甚至还能给我们提供一个安装的路径,模拟出windows上的C盘D盘E盘。但这只是一个库虚拟层。同样在windows上我们也能提供linux运行环境。叫cywin,在windows之上运行一个cywin,他能够提供运行模拟出linux的运行环境来。所以说有一些程序只能在linux上运行的话,我们也能在windows上基于cywin运行起来,比如说像docker。这都不是正常的方案,正常的方案就是,由于abf库是不兼容的,至少在二进制层次上他们是不兼容的。所以他们没有办法安装块系统来实现系统调用。
库级别的虚拟化:我们可以借助库级别的虚拟化来抹平他们的不同。比如在linux上我们可以借助于wine来提供windows库从而能够运行windows应用程序。而在Windoes上我们借助于Cywin这个程序包,来虚拟模拟出linux的运行环境。从而使得那些二进制程序也能跨系统来运行了。
系统级开发:
C/C++:服务及应用程序:httpd,vsftpd,nginx
go
应用级开发
java/Python/perl/ruby/php
java:hadoop,hbase,(他们的运行需要jvm就是java虚拟机)
Python:openstack(openstack是一个云操作系统)
运行Python程序需要用到pvm(Python虚拟机)
运行perl:(依赖于perl)
运行ruby:(依赖于ruby解释器)
运行php:(依赖于php解释器)
C/C++程序格式:
源代码:文本格式的程序代码;
二进制格式:文本格式的程序代码---->编译器------>二进制格式(二进制程序,库文件,配置文件,帮助文件)
(二进制格式我们仅仅是指他的陈序和库是二进制的,他的配置文件和帮助文件当然是文本的。我们知道Linux重要的哲学思想之一就是:用文本文件保存配置信息,这样带来的好处就在于,我们将来配置任何应用程序时,只需要依赖一款文本编辑器就可以。)
所以我们将来要想安装应用程序,那么针对我们两种格式的内容,他的安装方式就显然不一样,我们知道源代码不能运行,所以我们必须将其编译以后将其安装运行。对于源代码而言我们要手动把"文本格式的程序代码---->编译器------>二进制格式"这个过程手动完成。如果是别人给我们提供的是二进制格式的文件,上面的过程就不需要我们自己做了。因为我们拿到的直接是可运行格式的。万一很不幸的是对方仅提供了源代码怎么办呢?那么我们就只能自己编译了。而要想能够自己编译的话,那就依赖于编译开发环境。因为编译要依赖于编译器,依赖于头文件,依赖于开发库。我们的库也是源代码格式的,所以库也有两种文件。后来我们把它编译成了二进制格式的。
所以我们的编译开发环境依赖于:编译器,头文件,开发库。
如果我们拿到的是二进制格式的,那么就不需要编译,我们直接放到目录下就能运行起来了。
所以我们如果要执行源代码编译安装,那么我们需要额外的准备好几步。至少我们要想方设法保证我们的编译环境是完整的。而提供编译环境是相当劳心费神的工作。
我们学习程序包安装,首先了解二进制格式是怎么安装的,然后再去了解如何源代码编译安装。上面是C程序的格式。
那么如果是应用级的程序格式呢?
那么我们就以JAVA和Python为例,那么JAVA和Python应用程序格式是一样的,
java/python程序格式:
源代码
二进制
同样的道理,如果是源代码格式,那也只能编译了,如果是二进制格式那么直接使用即可
但是他们的编译不同在于,他们编译出来的不是二进制格式,或者不是能够直接在CPU上直接运行的二进制格式,而是编译成其能够在虚拟机上(jvm/pvm)运行的程序格式。也就是说通过虚拟机将其转换成能够运行的二进制格式。中间多了一层,所以性能很差。或者说比起C语言性能比较差。通常来说无论是C格式的源代码,还是java格式的源代码,通常他们的程序文件,都不止一个。那为什么不止一个?
将来我们的程序文件在编译时存在错综复杂的依赖关系,导致我们有一百个程序源文件,很有可能我们先编译第一个,在编译第三个,在编译第二个。因为第一个第三个被第二个所依赖。这样带来的结果就是谁先编译谁后编译,作为使用者我们没有能力管理他们的编译顺序。所以各种各样的源代码通常都使用一个项目管理工具。或者叫项目构建工具。
项目构建工具:
C/C++:最著名的项目构建工具就叫make
java:最经典的项目构建工具就叫maven
这样项目构建工具,也必须依赖项目开发环境才能构建。而对于java来讲他也有自己的开发环境。他也需要开发环境。只不过对于这两种的编程语言来讲。他们的开发环境,通常指的是,那个对应应用程序的虚拟机,和虚拟机上面的编译器。java源代码编译也需要开发环境,只不过是没有头文件,他们也需要:编译器,卡发库。这也是我们程序包的组成格式。
为了降低初级使用者的难度,我们应该怎样做?
我们应该使用程序包管理器,来协助这些终端用户的管理工作。
程序包管理器:
源代码---->目标二进制格式----->组织成为一个或有限几个"包"文件;
安装,升级,卸载,查询,(甚至对linux上还支持)校验
程序包管理器:
(程序包管理器大体上有哪几种呢?
对于windows来讲,大多数的应用程序都是exe格式的。这种格式应用程序给我们提供一个安装界面,我们只需点击下一步下一步即可,卸载的时候我们通过我们控制面板中的,卸载应用程序来实现,为什么我们能看到的只是下一步下一步就能完成安装呢?他其实就是通过一个程序包管理器打包成一个单个的exe文件,我们知道我们安装完以后他的确分散成多个可能放在program/files目录下某一个路径下,每一个应用程序都有一个目录,里面存放各种文件,有二进制的有库的,对于windows来说,他们的库是dll文件,动态链接库,dynamic link,而对于linux而言,叫so。)
目前linux有三大主流分支:
debian:dpt,dpkg,".dep"
redhat:redhat package manager,简称:rpm,".rpm";rpm ispackage manager;
S.u.S.E:rpm,".rpm",
Gentoo:ports
ArchLinux:
源代码:
命名方式:name-VERSION.tar.gz
VERSION:major.minor.release //主版本号.次版本号.发行版本
rpm包命名格式:
name-VERSION-release.arch.rpm //release是rpm包的release。
VERSION:major.minor.release
release.arc:是指rpm包的发行号
release.os:2.el7.i386.rpm
archetecture:架构,i386,x64(amd64),ppc,noarch
redis-3.0.2.targz----->redis-3.0.2-1.centos7.x64.rpm
changelog:
拆包:主包和支包
主包:name-VERSION-release.arch.rpm
支包:name-function-VERSION-release.arch.rpm
function:devel,utils,libs.....
依赖关系:
x,y,z
x------依赖--->y,z
y------依赖-------->A,B,C
c--------->y
前端工具:自动解决依赖关系;
yum:rhel系列系统上rpm包管理器的前端工具;
apt-get(apt-cache):dep包管理器的前端工具;
zypper:suse的rpm管理器前端工具;
dnf:Fedora 22+系统上rpm包管理器的前端工具;
程序包管理器:
功能:将编译好的应用程序的各组成文件打包成一个或几个程序包文件,从而更方便的 实现程序包的安装,升级,卸载,和查询等管理操作;
1.程序包的组成清单(每个程序包都单独实现);
文件清单
安装或卸载时运行的脚本
2数据库(公共)
程序包的名称和版本;
依赖关系;
功能说明;
安装生成的各个文件的文件路径及校验码信息;
CentOS系列系统的rpm数据库:路径
/var/lib/rpm
[root@centos7 ~]# ls /var/lib/rpm
Basenames __db.002 Group Obsoletename Requirename Triggername
Conflictname __db.003 Installtid Packages Sha1header
__db.001 Dirnames Name Providename Sigmd5
[root@centos7 ~]#
解释:
Group:包组,我们可以将程序划分成一个组,将来可以把一个程序包组全部安上,一个组 全部卸载。
Name:各个程序的名字;
Sigmd5:MD5的校验码;
Triggername:触发器名称;
获取程序包的途径:
(1)系统发行版的光盘或官方的文件服务器(或镜像站点):
http://mirrors.aliyun.com
http://mirrors.sohu.com
http://mirrors.163.com
(2)项目的官方站点
举例:以thhp为例:站点httpd.apache.org
或者:
网站www.zabbix.com
打开网站www.zabbix.com网站,我们网站的导航栏中直接点击"Download",打开一个页面,前面的"Zabbix Packages"是zabbix的rpm包,再往下"Zabbix Sources"是源码包。
所以说很多项目的官方站点也提供rpm包,并且我们一定注意,既然后能用rpm包安装的我们一定不要使用源码包编译安装。
(3)第三方组织:EPEL
EPEL:红帽官方的社区组织所维护的,发行光盘之外其他他们觉得比较有用比较重点,比较有名的程序包,都将制作成rpm包放在EPEL中。
其实国内的很多官方站点都有这样的epel。
举例演示,我们以"mirrors.aliyun.com"为例:
在镜像阿里云的站点上"mirrors.aliyun.com"也有epel,在epel中会为我们的centos提供了众多的额外的补充包。
(a)EPEL
(b)搜索引擎
http://pkgs.org(在rpm领域中,这是一个非常重要的);
rpmfind.net(要想搜哪个文件包直接搜。)
rpm.pbone.net
上面对话框中,我们可以输入正确的内容来进行查询,我们还可以通过后面的
Advanced RPM Search |
来进行高级查询。
(4)自己手动制作rpm包。
注意:不管上面的那种方式获得rpm包,只要是通过互联网上获得的,那么我们就可以认为即使原作者在里面没有做任何改变,或者修改,因为我们现在经常使用一些下载工具,像迅雷,那这种工具有点问题,为什么这种工具他的下载的速度非常的块,就是因为他们可能不是从官方的原站点下载的,或者是非完完全全的官方站点上下载的,其实从已经下载的用户的那里下载的,如果官方站点下载不到的话,而且这时候他恰恰搜索到某个用户的那里有这个文件,他也会传给你,但是这个文件可能被其他用户精心的修改过,制作了后门,所以以后我们在互联网上下载人格安全性较高的文件的,像银行官方站点的插件,还有像支付宝的证书等,我们就不应该在使用迅雷下载。以后这中工具少用,尤其是使用PHP下载的,是相当危险的,那么我们下载下来一个工具我们不知道他到底是不是官方提供的呢?
至少是所有的数据没有被篡改过,那怎么办呢?
我们建议要做MD5校验,提供一个MD5校验器,检验其合法性,来源合法性。
程序包的完整性要做校验;
CentOS系统上rpm命令管理程序包:
安装,升级,卸载,查询和校验,数据库的维护
上面提到的"安装,升级,卸载,查询和校验"都用rpm命令来实现。
格式: rpm [OPTIONS] [PACKAGE_FILE]
安装用到的选项:-i=--install
升级用到的选项:-U=--update, -F=--freshen
卸载:-e=--erase
查询:-q=--query
校验:-V=--verify
数据库维护:--builddb,--initdb
安装:
安装时必须有对应的文件才行。
rpm {-i|--install} [install-options]PACKAGE_FILE ...
真正安装的时候应该使用选项:-ivh
rpm -ivh PACKAGE_FILE......
GENERAL OPTIONS(通用选项)
-v:verbose;(输出相信信息)
-vv:(输出更详细的过程信息)
[install-options]
-h:hash marks输出进度条;每个#表示2%的进度;
--test:如果不想真正的安装,仅仅是检查一下有没有潜在的冲 突的可能我们就可以测试安装,检查并报告依赖关系及 冲突消息等;
--nodeps:忽略依赖关系;不建议;
--replacepkgs:重新安装 (如果某个包安装过,但是后来我们 更改了他的配置文件,出了错,那我们刻意先卸载 再重新安装,但是我们还有一个更好的方法就是, 直接重新安装。)
--noscripts:
--oldpackage:降级用的
--justdb:只是升级一下数据库。
注意rpm包可以自带脚本:
这些脚本有四类:
如果这四类都不想执行:--noscripts
preinstall:安装过程开始之前运行脚本,%pre --nopre
postinstall:安装过程完成以后运行的脚本,%post --nopost
preuninstall:卸载过程真正开始执行之前运行的脚本,%preun --nopreun
postuninstall:卸载过程完成之后运行的脚本,%postun --nopostun
--nosignature:不检查签名信息,不检查来源合法性;
--nodigest:不检查包完整性信息;
举例演示:
[root@centos6 Packages]# rpm -ivh zsh-4.3.11-4.el6.centos.2.x86_64.rpm
warning:zsh-4.3.11-4.el6.centos.2.x86_64.rpm: Header V3 RSA/SHA1 Signature, key IDc105b9de: NOKEY
Preparing... ###########################################[100%]
1:zsh ########################################### [100%]
[root@centos6 Packages]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
/bin/tcsh
/bin/csh
/bin/zsh
[root@centos6 Packages]#
演示重新安装replacepkgs:
之前我们zsh已经安装过了,那我们先编辑一下zsh的配置文件"/etc/zshrc",比方说我们删除其中的几行,然后保存,因为我们执行"wq"之后,他的配置文件信息就不能恢复了。那么这时,我们
[root@centos6 media]# vim /etc/zshrc //先将zsh的配置文件中的内容删除一部分
[root@centos6 media]# cat /etc/zshrc
[root@centos6media]#rpm -ivh --replacepkgs /media/Packages/zsh-4.3.11-4.el6.centos.2.x86_64.rpm
[root@centos6media]# cat /etc/zshrc //发现配置文件内容没有恢复,这时因为我们的系统在我们没有将原先的配置文件删除,就在重装软件,那么系统就会认为我们这个配置文件修改是有目的的,我们也要记住replacepkgs是不能修改原来的配置文件的。所以我们在重装之前要先删除配置文件。
[root@centos6media]# rm -f /etc/zshrc
[root@centos6 media]# rpm -ivh --replacepkgs/media/Packages/zsh-4.3.11-4.el6.centos.2.x86_64.rpm
[root@centos6media]# cat /etc/zshrc //发现配置文件内容恢复了
#
# /etc/zshrc is sourced in interactiveshells. It
# should contain commands to set upaliases, functions,
# options, key bindings, etc.
#
## shell functions
#setenv() { export $1=$2 } # csh compatibility
# Set prompts
PROMPT='[%n@%m]%~%# ' # default prompt
#RPROMPT=' %~' # prompt for right side of screen
# bindkey -v # vi key bindings
# bindkey -e # emacs key bindings
bindkey ' ' magic-space # also do history expansion on space
_src_etc_profile_d()
{
# Make the *.sh things happier,and have possible ~/.zshenv options like
#NOMATCH ignored.
emulate -L ksh
#from bashrc, with zsh fixes
if [[ ! -o login ]]; then # We're not a login shell
for i in /etc/profile.d/*.sh; do
if [ -r "$i" ]; then
. $i
fi
done
unset i
fi
}
_src_etc_profile_d
unset -f _src_etc_profile_d
[root@centos6 media]#
不检查签名演示:
[root@centos6 media]# rpm -ivh --replacepkgs/media/Packages/zsh-4.3.11-4.el6.centos.2.x86_64.rpm
warning: /media/Packages/zsh-4.3.11-4.el6.centos.2.x86_64.rpm: Header V3RSA/SHA1 Signature, key ID c105b9de: NOKEY
Preparing... ########################################### [100%]
1:zsh ########################################### [100%
上面在重新安装软件包的时候,前面出现了警告,我们要见检查文件的合法性,文件的完整性,要检查文件的这两个选项,要依赖一个秘钥文件,要依赖这个包制作者的公钥。
[root@centos6 media]# rpm -ivh--replacepkgs --nosignature/media/Packages/zsh-4.3.11-4.el6.centos.2.x86_64.rpm
Preparing... ###########################################[100%]
1:zsh ########################################### [100%]
[root@centos6 media]#
上面安装时,警告消失。