常见的Linux发行版主要可以分为两类,类ReadHat系列和类Debian系列,这里我们是以其软件包的格式来划分的,这两类系统分别提供了自己的软件包管理系统和相应的工具。
rpm的全称是Redhat Package Manager,常见的使用rpm软件包的系统主要有Fedora、CentOS、openSUSE、SUSE企业版、PCLinuxOS以及Mandriva Linux、Mageia等。使用deb软件包后缀的类Debian系统最常见的有Debian、Ubuntu、Finnix等。
从软件运行的结构来说,一个软件主要可以分为三个部分:可执行程序、配置文件和动态库。当然还有可能会有相关文档、手册、供二次开发用的头文件以及一些示例程序等等。其他部分都是可选的,只有可执行文件是必须的
1.安装一个包
# rpm -ivh < rpm package name>
2.安装参数
--force 即使覆盖属于其它包的文件也强迫安装
--nodeps 如果该RPM包的安装依赖其它包,即使其它包没装,也强迫安装。
3.升级一个包
# rpm -Uvh < rpm package name>
4.移除一个包
# rpm -e < rpm package name>
5.查询一个包是否被安装
# rpm -q < rpm package name>
6.得到被安装的包的信息
# rpm -qi < rpm package name>
7.列出该包中有哪些库和头文件
# rpm -ql < rpm package name>
8.列出服务器上的一个文件属于哪一个RPM包
#rpm -qf + 文件名
9.可综合好几个参数一起用
# rpm -qil < rpm package name>
10.列出所有被安装的rpm package
# rpm -qa
11.列出一个RPM包文件中包含有哪些文件
# rpm -qlp < rpm package name>
12.解压一个rpm包
# rpm2cpio xxx.rpm | cpio -idm
关于如何制作rpm软件包的方法,网上教程也一大堆,谈及最多的当属rpmbuild这个命令行工具(如果自己系统上没有rpmbuild命令就安装之:yum install rpm* rpm-build rpmdev*
)。用rpmbuild制作rpm包的主要步骤如下:
1,执行rpmdev-setuptree
会在当前用户家目录下的rpmbuild目录(如果该目录不存在也会被自动创建)里自动建立以下6个子目录:
目录名 | 说明 | macros中的宏名 |
---|---|---|
BUILD | 编译rpm包的临时目录 | %_builddir |
BUILDROOT | 编译后生成的软件临时安装目录 | %_buildrootdir |
RPMS | 最终生成的可安装rpm包的所在目录 | %_rpmdir |
SOURCES | 所有源代码和补丁文件的存放目录 | %_sourcedir |
SPECS | 存放SPEC文件的目录(重要) | %_specdir |
SRPMS | 软件最终的rpm源码格式存放路径 | %_srcrpmdir |
2,将源码sample.tar.gz放在 /root/rpmbuild/SOURCES/
目录下
3,在 /root/rpmbuild/SPECS/
目录下编写 main.spec文件,具体内容在后面介绍
4,在 /root/rpmbuild/
目录下执行:
rpmbuild -ba SPECS/main.spec
在/root/rpmbuild/RPMS/x86_64/
下将生成二进制rpm包
在/root/rpmbuild/SRPMS/
下将生成含源码的rpm包
安装rpm包: rpm -ivh sample-1.0.0-1.rpm
制作rpm包的关键就是上面的SPEC文件的写法,我们可以用rpmdev-newspec -o Name-version.spec命令来生成SPEC文件的模板,然后在上面修改就可。例如:
[root@localhost ~]# rpmdev-newspec -o myapp-0.1.0.spec
Skeleton specfile (minimal) has been created to "myapp-0.1.0.spec".
[root@localhost ~]# cat myapp-0.1.0.spec
Name: myapp-0.1.0
Version:
Release: 1%{?dist}
Summary:
Group:
License:
URL:
Source0:
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires:
Requires:
%description
%prep #这个阶段主要完成对源代码包的解压和打补丁
%setup -q #静默模式解压并cd
#%patch0 -p1 #如果需要在这打补丁,依次写
%build #这个阶段就是执行常见的configure和make操作
%configure #%configure 也可以用./configure来替换
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
%doc
%changelog #这是最后一个阶段,主要记录的每次打包时的修改变更日志
总结一下制作rpm包时spec文件的几个关键阶段,以及所发生的事情:
阶段 | 动作 |
---|---|
%prep | 将%_sourcedir目录下的源代码解压到%_builddir目录下。如果有补丁的需要在这个阶段进行打补丁的操作 |
%build | 在%_builddir目录下执行源码包的编译。一般是执行./configure和make指令 |
%install | 将需要打包到rpm软件包里的文件从%_builddir下拷贝%_buildrootdir目录下。当用户最终用rpm -ivh name-version.rpm安装软件包时,这些文件会安装到用户系统中相应的目录里 |
制作rpm包 | 这个阶段是自动完成的,所以在SPEC文件里面是看不到的,这个阶段会将%_buildroot目录的相关文件制作成rpm软件包最终放到%_rpmdir目录里 |
%clean | 编译后的清理工作,这里可以执行make clean以及清空%_buildroot目录等 |
更详细的例子:
### 0.define section #自定义宏段,这个不是必须的
### %define nginx_user nginx #这是我们自定义了一个宏,名字为nginx_user值为nginx,%{nginx_user}引用
### 1.The introduction section #介绍区域段
Name: tengine #名字为tar包的名字
Version: 1.4.2 #版本号,一定要与tar包的一致哦
Release: 1%{?dist} #释出号,也就是第几次制作rpm
Summary: tengine from TaoBao #软件包简介,最好不要超过50字符
Group: System Environment/Daemons #组名,可以通过less /usr/share/doc/rpm-4.8.0/GROUPS 选择合适组
License: GPLv2 #许可,GPL还是BSD等
URL: http://laoguang.blog.51cto.com #可以写一个网址
Packager: Laoguang
Vendor: TaoBao.com
Source0: %{name}-%{version}.tar.gz
#定义用到的source,也就是你收集的,可以用宏来表示,也可以直接写名字,上面定义的内容都可以像上面那样引用
#patch0: a.patch #如果需要补丁,依次写
BuildRoot: %_topdir/BUILDROOT
#这个是软件make install 的测试安装目录,也就是测试中的根,我们不用默认的,我们自定义,
#我们可以来观察生成了哪此文件,方便写file区域
BuildRequires: gcc,make #制作过程中用到的软件包
Requires: pcre,pcre-devel,openssl,chkconfig #软件运行需要的软件包,也可以指定最低版本如 bash >= 1.1.1
%description #软件包描述,尽情的写吧
It is a Nginx from Taobao. #描述内容
### 2.The Prep section 准备阶段,主要目的解压source并cd进去
%prep #这个宏开始
%setup -q #这个宏的作用静默模式解压并cd
#%patch0 -p1 #如果需要在这打补丁,依次写
### 3.The Build Section 编译制作阶段,主要目的就是编译
%build
./configure \ #./configure 也可以用%configure来替换
--prefix=/usr \ #下面的我想大家都很熟悉
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_flv_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--http-client-body-temp-path=/var/tmp/nginx/client/ \
--http-proxy-temp-path=/var/tmp/nginx/proxy/ \
--http-fastcgi-temp-path=/var/tmp/nginx/fcgi/ \
--http-uwsgi-temp-path=/var/tmp/nginx/uwsgi \
--http-scgi-temp-path=/var/tmp/nginx/scgi \
--with-pcre
make %{?_smp_mflags} #make后面的意思是:如果就多处理器的话make时并行编译
### 4.Install section 安装阶段
%install
rm -rf %{buildroot} #先删除原来的安装的,如果你不是第一次安装的话
make install DESTDIR=%{buildroot}
#DESTDIR指定安装的目录,而不是真实的安装目录,%{buildroot}你应该知道是指的什么了
### 4.1 scripts section #没必要可以不写
%pre #rpm安装前制行的脚本
if [ $1 == 1 ];then #$1==1 代表的是第一次安装,2代表是升级,0代表是卸载
/usr/sbin/useradd -r nginx 2> /dev/null ##其实这个脚本写的不完整
fi
%post #安装后执行的脚本
%preun #卸载前执行的脚本
if [ $1 == 0 ];then
/usr/sbin/userdel -r nginx 2> /dev/null
fi
%postun #卸载后执行的脚本
### 5.clean section 清理段,删除buildroot
%clean
rm -rf %{buildroot}
### 6.file section 要包含的文件
%files
%defattr (-,root,root,0755) #设定默认权限,如果下面没有指定权限,则继承默认
/etc/ #下面的内容要根据你在%{rootbuild}下生成的来写
/usr/
/var/
### 7.chagelog section 改变日志段
%changelog
* Fri Dec 29 2012 laoguang - 1.0.14-1
- Initial version
关于./configure生成的Makefile,可以参考这篇文章便于理解:《make、Makefile &静态库、动态库》:
https://blog.csdn.net/qq_15437629/article/details/77433536
gcc优化及特定编译安装示例:
#!/bin/sh
CFLAGS="-g -O2 -Wall -Werror -Wno-unused"
CXXFLAGS="-g -O2 -Wall -Werror -Wno-unused"
PKG_ROOT=/mnt
PKG_DIR=pkgname
export CFLAGS CXXFLAGS
./configure --prefix=/$PKG_DIR --sysconfdir=/$PKG_DIR/etc
make
make DESTDIR=$PKG_ROOT install
# end
如果在执行./configure以前设置环境变量export CFLAGS,那么执行configure以后,Makefile将会设置这个选项,链接时就会有这个参数。关于gcc编译器 CFLAGS 的参数说明,详见:
https://blog.csdn.net/qq_15437629/article/details/85808229
默认软件最后会安装于/pkgname目录下,配置文件会安装于/pkgname/etc目录下;
但在make install中添加DESTDIR参数,则会以此参数对应变量作为安装时根目录;
即软件会安装于/mnt/pkgname目录下,配置文件会安装于/mnt/pkgname/etc目录下
补充:
linux程序的存放目录大致有三个地方:
通常来说我们安装程序就安装在 /usr/local目录下。下面区别下/sbin和/bin:
而/usr/bin,/usr/sbin与/sbin /bin目录的区别在于:
/bin,/sbin目录是在系统启动后挂载到根文件系统中的,所以/sbin,/bin目录必须和根文件系统在同一分区;/usr/bin,usr/sbin可以和根文件系统不在一个分区。
/usr/sbin存放的一些非必须的系统命令;/usr/bin存放一些用户命令,如led(控制LED灯的)。
转下一位网友的解读,个人认为诠释得很到位:
/bin是系统的一些指令。bin为binary的简写主要放置一些系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar等。
/sbin一般是指超级用户指令。主要放置一些系统管理的必备程式例如:cfdisk、dhcpcd、dump、e2fsck、fdisk、halt、ifconfig、ifup、 ifdown、init、insmod、lilo、lsmod、mke2fs、modprobe、quotacheck、reboot、rmmod、 runlevel、shutdown等。
/usr/bin 是你在后期安装的一些软件的运行脚本。主要放置一些应用软体工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome*、 gzip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb*、wget等。
/usr/sbin 放置一些用户安装的系统管理的必备程式例如:dhcpd、httpd、imap、in.*d、inetd、lpd、named、netconfig、nmbd、samba、sendmail、squid、swap、tcpd、tcpdump等。
如果新装的系统,运行一些很正常的诸如:shutdown,fdisk的命令时,提示:bash:command not found。那么首先就要考虑root 的$PATH
里是否已经包含了这些环境变量。可以查看PATH,如果是:PATH=$PATH:$HOME/bin
,则需要添加成如下:
PATH=$PATH:$HOME/bin:/sbin:/usr/bin:/usr/sbin