源码编译三部曲(以nginx示例)

Posted Tuki_a

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了源码编译三部曲(以nginx示例)相关的知识,希望对你有一定的参考价值。

源码编译三部曲

什么是源码编译

源代码是相对目标代码和可执行代码而言的。源代码就是用汇编语言和高级语言写出来的代码。
目标代码是指源代码经过编译程序产生的能被cpu直接识别二进制代码。
可执行代码就是将目标代码链接后形成的可执行文件,当然也是二进制的。

在现代程序语言中,源代码可以是以书籍或者磁带的形式出现,但最为常用的格式是文本文件,这种典型格式的目的是为了编译出计算机程序。计算机源代码的最终目的是将人类可读的文本翻译成为计算机可以执行的二进制指令,这种过程叫做编译,通过编译器完成。即源码要运行,必须先转成二进制的机器码。这是编译器的任务。

编译过程流程图:下图转自Linux下源码编译安装详解

为什么要选择源码编译

因为官方为我们提供的mysqlphp等其功能有限,我们自行编译,是为了定制化,可以在编译过程中添加需要的功能模块。

rpm包与源码包区别

  • 1、源码包是开源的,安装更自由,安装效率更高,但是它安装更慢,更容易报错;rpm包是经过编译的,安装更快,报错容易解决,只有依赖性的相关问题。
  • 2、rpm包不需要知指定安装位置,它会安装在系统的默认位置中;而源码包需要人为指定安装位置。导致了后续管理的不同,一般放在/usr/local下,/usr/local是系统专门安装外来软件的目录。
  • 3、rpm包安装时的二进制文件是会把模块编译进来的,但每个模块并不是默认都会开启的,如果想添加第三方的模块,那么必须通过源码编译安装进行定制化安装。

源码编译三部曲

在Linux中利用源码包安装软件最重要的就是要仔细阅读安装包当中的README INSTALL两个说明文件,这两个文件会清楚的告诉你如何可以正确的完成这个软件的安装!

以编译安装nginx为例,nginx官方文档:http://nginx.org/en/docs/

预编译./configure

编译器在开始工作之前,需要知道当前的系统环境,比如标准库在哪里、软件的安装位置在哪里、需要安装哪些组件等等。这是因为不同计算机的系统环境不一样,通过指定编译参数,编译器就可以灵活适应环境,编译出各种环境都能运行的机器码。这个确定编译参数的步骤,就叫做"配置"(configure)。

这些配置信息保存在一个配置文件之中,约定俗成是一个叫做configure的脚本文件。通常它是由autoconf工具生成的。编译器通过运行这个脚本,获知编译参数。

configure脚本已经尽量考虑到不同系统的差异,并且对各种编译参数给出了默认值。如果用户的系统环境比较特别,或者有一些特定的需求,就需要手动向configure脚本提供编译参数

预编译./configure就是测试存在的特性或者bug(检测软件满足不满足安装条件)然后来建立Makefile文件来完成make!,产生的makefile文件里边记录了编译参数。

解压nginx源码包并进入解压目录

[root@server1 ~]# tar zxf nginx-1.20.1.tar.gz 	#解压
[root@server1 ~]# cd nginx-1.20.1/
[root@server1 nginx-1.20.1]# ./configure --help	#查看可带参数,with就是默认编译没有的,如果自己有需求可以添加;without就是默认编译有的,如果不想要要加上这些参数


我选择了以下参数想要定制安装nginx

[root@server1 nginx-1.20.1]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio

--prefix=/usr/local/nginx	#指定安装地址
--with-http_ssl_module		#ssl模块,支持https
--with-http_stub_status_module	#监控nginx的整体访问情况
--with-threads				#多线程,添加线程池机制
--with-file-aio				#aio就是异步I/O,允许进程进行不受阻塞或不需要等待I/O完成的I/O操作

预编译报错,少c的编译环境,安装gccyum install -y gcc
#错误不能跳过,警告可以跳过

再预编译报错,根据报错安装yum install -y pcre-devel,pcre-devel是使用PCRE做二次开发时所需要的开发库,包括头文件等,这也是编译Nginx所必须使用的

再预编译报错,根据报错安装yum install -y openssl-devel

再预编译,这回编译成功,同时可以看到./configure执行后产生了objs这个目录以及.c文件

编译make

预编译成功完成后,证明我们的系统环境已经满足安装环境了,就可以正式编译了。

编译完后产生makefile文件,里边记录了安装的参数(包括我们指定的)

make正式编译,不加参数的make的作用就是从当前目录下的Makefile文件中读取指令,对源代码进行编译

在每次使用make时,都会重新生成objects,新产生的object会覆盖旧的objects。同时产生了新的nginx二进制文件。c语言都会先生成目标文件,最后生成可执行文件,由.o文件最后编译出来了nginx二进制文件

安装make install

如果原始代码编译无误,且执行结果正确,便可以make install把程序安装至系统预设的可执行文件存放路径,最后可以运行make clean删除临时文件。

安装在了我们指定的路径

启动nginx

执行二进制程序即可启动,注意不能重复启动,否则会报错

启动成功!

怎么卸载源码安装的软件

想卸载源码方式安装的软件,直接删除安装目录即可!

nginx优化

查看nginx二进制程序的大小

执行make clean清理掉源码安装nginx时的临时数据

[root@server1 nginx-1.20.1]# make clean
rm -rf Makefile objs

关掉gcc的debug模式,这样编译安装都会快很多

[root@server1 nginx-1.20.1]# cd auto/
[root@server1 auto]# cd cc
[root@server1 cc]# ls
acc  bcc  ccc  clang  conf  gcc  icc  msvc  name  owc  sunc
[root@server1 cc]# vim gcc

注释掉如图内容

vim src/core/nginx.h可以修改版本信息,让执行nginx -v时按照自己想显示的内容显示

重新预编译,以及编译

[root@server1 nginx-1.20.1]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module --with-threads --with-file-aio
[root@server1 nginx-1.20.1]# make

编译成功后会在objs中生成可执行文件,此时文件大小远小于之前

先关闭nginx

将此nginx的二进制文件放入之前的路径下即可更新/usr/local/nginx/sbin/,nginx的更新只需要替换二进制文件即可

[root@server1 objs]# rm -fr /usr/local/nginx/sbin/nginx
[root@server1 objs]# cp nginx /usr/local/nginx/sbin/

直接使用nginx二进制程序控制nginx

到nginx二进制程序目录下使用或者在其他目录时使用绝对路径使用

/usr/local/nginx/sbin/nginx 			#开启nginx
/usr/local/nginx/sbin/nginx -s stop 	#停止nginx
/usr/local/nginx/sbin/nginx -s reload 	#重载nginx

全局使用nginx命令控制nginx

将nginx二进制文件链接进系统PATH 内,可以直接使用nginx命令启用nginx

[root@server1 objs]# ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/
[root@server1 objs]# which nginx
/usr/local/sbin/nginx
[root@server1 objs]# cd
[root@server1 ~]# echo $PATH	#查看系统环境变量
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin


现在就可以全局使用nginx了,不用再指定路径,nginx -t 是测试nginx配置有没有问题,如果有问题是不能正常启动nginx的

nginx命令就是启动nginx

使用systemctl命令来控制nginx

每一个 Unit(服务等) 都有一个配置文件,告诉 Systemd 怎么启动这个 Unit 。Systemd 默认从目录/etc/systemd/system/读取配置文件。
但是,里面存放的大部分文件都是符号链接,指向目录/usr/lib/systemd/system/,真正的配置文件存放在那个目录。 systemctl enable 命令用于在上面两个目录之间,建立符号链接关系。

systemd有系统和用户区分:
系统(/user/lib/systemd/system/)
用户(/etc/lib/systemd/user/)
一般系统管理员手工创建的单元文件建议存放在/etc/systemd/system/目录下面。

用systemctl命令操作服务其实就是操作xxx.service文件

[root@server1 system]# cd /usr/lib/systemd/system/
[root@server1 system]# vim nginx.service #编写nginx的配置文件,内容如下
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target


记得配置文件里的路径要和你自己编译安装时的路径一致

使用systemctl命令来控制启动nginx失败

看日志是什么错误

[root@server1 system]# cat /var/log/messages 

是80端口被占用了,之前我们开启了nginx没关,所以现在才会显示被占用

用systemctl命令关nginx关不掉,直接关二进制程序也不行

[root@server1 system]# systemctl stop nginx
[root@server1 system]# nginx -s stop

只好看下进程号,逐一kill掉

这时候就可以使用systemctl命令来控制nginx了

以上是关于源码编译三部曲(以nginx示例)的主要内容,如果未能解决你的问题,请参考以下文章

Lamp架构nginxphpmysql源码编译安装

Lamp架构nginxphpmysql源码编译安装

Nginx三部曲

2-21-源码编译搭建LNMP环境

CentOS 7.2源码包编译安装nginx-1.10.2

源码编译安装Nginx服务及访问控制(实战!)