刘泉皓

没有最强的法术,只有最强的法师。

nginx学习(3)——搭建一台web服务器

11 Jul 2018 » memory

好了,经过前面的尝试,我已经有了一个可以运行的nginx了,这还挺开心的,现在只要我有源码,就可以构建出nginx,然后放到一台机器里运行web服务了。接下来就开始配置nginx来运行web服务。

首先,我贴出最基本的目录,这是一个开始:

liuxu:test$ tree
.
├── conf
│   └── nginx.conf
├── logs
│   └── error.log
└── nginx

2 directories, 5 files

这是一个基本目录情况,nginx在当前目录,与它同级的是conf/logs/,这些目录在编译时都是可改的,只是目前我用最简编译是这个目录结构。

然后配置conf/nginx.conf

liuxu:test$ cat conf/nginx.conf
events{}

http {
    server {
    }
}

很简单,event{}是nginx强制需要配置的。然后我需要运行的是http服务器,所以有了http{}。然后在http里面添加一个server{},表示配置一台服务器。如果需要多台服务器,就添加多个server{}就好了,很简单的。

现在我们运行一下,看看能不能运行:

liuxu:test$ ./nginx -p .
liuxu:test$ ps aux | grep nginx
liuxu    15072  0.0  0.0  14288   332 ?        Ss   17:27   0:00 nginx: master process ./nginx -p .
liuxu    15073  0.0  0.0  14452  1240 ?        S    17:27   0:00 nginx: worker process
liuxu    15130  0.0  0.0  21536  1092 pts/1    R+   17:28   0:00 grep --color=auto nginx
liuxu:test$ ss -anpt | grep nginx
LISTEN     0        128               0.0.0.0:8000              0.0.0.0:*        users:(("nginx",pid=15073,fd=6),("nginx",pid=15072,fd=6))
liuxu:test$./nginx -p . -s stop
liuxu:test$ sudo ./nginx -p .
liuxu:test$ sudo ss -anpt | grep nginx
LISTEN     0        128               0.0.0.0:80                0.0.0.0:*        users:(("nginx",pid=16202,fd=6),("nginx",pid=16201,fd=6))
liuxu:test$ sudo ./nginx -p . -s stop

好了,就这么运行起来了,只有一个nginx主进程和一个工作进程,但足够了,可以运行网站了。工作进程默认监听0.0.0.0:8000,表示监听本机所有地址,所有地址就是即监听本机127.0.0.1,如果有其他ip,也会监听,例如我还有个局域网ip192.168.1.155,用这两个地址都能访问我的web服务器。默认监听端口是8000,但是如果你是root权限,会默认监听80端口,就像用sudo执行的时候那样。现在我们来访问一下看看。

liuxu:test$ curl http://localhost:8000/
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html
liuxu:test$ curl http://192.168.1.155:8000/
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html>
liuxu:test$ curl http://192.168.1.155:7000/
curl: (7) Failed to connect to 192.168.1.155 port 7000: Connection refused

看,成功返回404了,代表访问服务器成功,但是没有找到内容,当然找不到,因为我们根本就没有设置任何内容用于返回。最后一次访问没有监听的7000端口,所以会返回连接被拒绝,这代表没有服务监听7000端口。

现在为了在访问网站时去掉后面的:8000,我们让服务器一直监听80端口。在我们访问网站的时候,例如http://www.liuquanhao.com/,其实访问的是http://www.liuquanhao.com:80/,因为http默认是80端口,所以我们平时可以省略,浏览器会自动访问服务器80端口。顺便说一下,如果访问的网站是https的,那么会默认访问服务器的443端口,这个https服务器需要额外配置。

好了,我们来配置监听80端口:

liuxu:test$ cat conf/nginx.conf 
events{}

http {
    server {
        listen 80;
    }
}

贼简单,就一个listen 80;就可以了,表示监听本机所有地址的80端口。listen表示监听地址和端口,例如写listen 127.0.0.1:80,表示监听本机回环地址127.0.0.1,监听端口80;表示指令结束。

现在重新访问看看:

liuxu:test$ ./nginx -p . -s stop
liuxu:test$ ./nginx -p .
nginx: [emerg] bind() to 0.0.0.0:80 failed (13: Permission denied)
liuxu:test$ sudo ./nginx -p .
liuxu:test$ ps aux | grep nginx
root     16966  0.0  0.0  22744   368 ?        Ss   18:02   0:00 nginx: master process ./nginx -p .
nobody   16967  0.0  0.0  27288  2692 ?        S    18:02   0:00 nginx: worker process
liuxu    16969  0.0  0.0  21536  1012 pts/1    S+   18:02   0:00 grep --color=auto nginx
liuxu:test$ ss -anpt | grep nginx
liuxu:test$ sudo ss -anpt | grep nginx
LISTEN      0        128               0.0.0.0:80               0.0.0.0:*        users:(("nginx",pid=16967,fd=6),("nginx",pid=16966,fd=6))

因为linux服务器中小于等于1024的端口需要root权限才能使用,所以如果nginx配置监听80端口,普通用户权限是无法启动的,需要用sudo命令或root账户才能启动。

现在访问看看:

liuxu:test$ curl http://127.0.0.1:80/
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html>
liuxu:test$ curl http://127.0.0.1/
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html>
liuxu:test$ curl http://192.168.1.155/
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html>

很愉快,运行成功了。但是很不开心,都是404,我想弄点东西输出,所以我开始配置一下:

liuxu:test$ mkdir html
liuxu:test$ echo "liuquanhao is best." > html/index.html
liuxu:test$ sudo tree
.
├── client_body_temp
├── conf
│   └── nginx.conf
├── fastcgi_temp
├── html
│   └── index.html
├── logs
│   ├── access.log
│   ├── error.log
│   └── nginx.pid
├── nginx
├── proxy_temp
├── scgi_temp
└── uwsgi_temp

liuxu:test$ curl http://127.0.0.1/
liuquanhao is best.

那些..._temp都是nginx运行时生成的,不用管它们。因为nginx默认将网页放在工作目录下的html/目录中,所以我新建了html目录。而我们访问一个域名,而且以/结尾的时候,其实访问的时/index.html,例如我访问http://www.liuquanhao.com/,其实访问的是http://www.liuquanhao.com/index.html,这个可以用nginx服务器设置,将默认访问的网页改为别的。可以看到,我访问成功了。

到现在为止,基本上一个网站已经可以放到html/,然后到弄一台有外网ip的服务器运行了,但是目前我们都是用ip地址访问的网站,不专业,现在就配置用域名来访问。

liuxu:test$ cat conf/nginx.conf
events{}

http {
    server {
        listen 80 default_server;
        return 404;
    }
    server {
        listen 80;
        server_name haha.ooo;
    }
}

很简单,添加了一个server_name haha.ooo;,这样就可以用http://haha.ooo/这个域名访问了。它的工作原理是这样:首先用浏览器访问这个网站,会提交http请求信息,里面包含Host: xxxx,例如访问的是http://127.0.0.1/,Host就是Host: 127.0.0.1,用http://haha.ooo/访问,Host就是Host: haha.ooo。当服务器收到请求的时候,会分析这个Host,用来匹配server_name配置的域名,匹配上了就说明访问的是这个server{}服务器。如果没匹配到,nginx就把这个请求导向一台默认服务器上,这个默认服务器是这个请求中端口下的默认服务器。这里是80,所以80下有一台默认默认服务器,如果配置里没设置,就是第一个server{},或者可以自己设置一个server{},里面添加listen 80 default_server;,这个default_server关键字就是设定当前所在server{}是listen中端口下的默认服务器。我这里设置了默认服务器直接返回404,也就是如果不是访问haha.ooo这个域名的服务器都访问默认服务器,默认服务器会直接返回404错误给你。

为了在本机测试,需要先修改/etc/hosts配置,将haha.ooo这个域名指向127.0.0.1

liuxu:test$ cat /etc/hosts
127.0.0.1 localhost

127.0.0.1 haha.ooo

可以看到,我把127.0.0.1 haha.ooo添加到了/etc/hosts中,里面还有个127.0.0.1 localhost是默认存在的,现在我们可以测试一下了。

liuxu:test$ sudo ./nginx -p . -s stop
liuxu:test$ sudo ./nginx -p .
liuxu:test$ ss -anpt | grep nginx
liuxu:test$ sudo ss -anpt | grep nginx
LISTEN     0        128               0.0.0.0:80                0.0.0.0:*        users:(("nginx",pid=22680,fd=6),("nginx",pid=22679,fd=6))

nginx启动成功。

liuxu:test$ ping haha.ooo
PING haha.ooo (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.018 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.046 ms
^C
--- haha.ooo ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1007ms
rtt min/avg/max/mdev = 0.018/0.032/0.046/0.014 ms

haha.ooo这个域名指向了127.0.0.1这个ip。

liuxu:test$ curl -lv http://haha.ooo/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to haha.ooo (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: haha.ooo
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.14.0
< Date: Wed, 11 Jul 2018 11:50:05 GMT
< Content-Type: text/html
< Content-Length: 20
< Last-Modified: Wed, 11 Jul 2018 10:10:50 GMT
< Connection: keep-alive
< ETag: "5b45d7aa-14"
< Accept-Ranges: bytes
< 
liuquanhao is best.
* Connection #0 to host haha.ooo left intact

haha.ooo 访问成功。

liuxu:test$ curl -lv http://127.0.0.1/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 404 Not Found
< Server: nginx/1.14.0
< Date: Wed, 11 Jul 2018 11:50:10 GMT
< Content-Type: text/html
< Content-Length: 169
< Connection: keep-alive
< 
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html>
* Connection #0 to host 127.0.0.1 left intact
liuxu:test$ curl -lv http://localhost/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 404 Not Found
< Server: nginx/1.14.0
< Date: Wed, 11 Jul 2018 11:50:17 GMT
< Content-Type: text/html
< Content-Length: 169
< Connection: keep-alive
< 
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html>
* Connection #0 to host localhost left intact

其他域名和ip访问服务器返回默认服务器返回的404。

这里额外解释一下http请求:

liuxu:test$ curl -lv http://127.0.0.1/
...
* Connected to haha.ooo (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: haha.ooo
...

在请求里我们看到有这一段,可以看见我们访问的是http://127.0.0.1/。就像前面说的,当访问http的网站时,默认时访问80端口,这里就可以看见* Connected to haha.ooo (127.0.0.1) port 80 (#0),访问80端口。接着是> GET / HTTP/1.1,代表获取/这个目录,服务器看到这个/后,会返回当前server{}默认的html目录下的index.html文件。接着是> Host: haha.ooo,这就是请求头的Host,服务器拿到这个后,会匹配自己server{}中配置的server_name

下面在看一个请求:http://haha.ooo,最后面没有/

liuxu:test$ curl -lv http://haha.ooo
* Rebuilt URL to: http://haha.ooo/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to haha.ooo (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: haha.ooo
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.14.0
< Date: Wed, 11 Jul 2018 11:57:03 GMT
< Content-Type: text/html
< Content-Length: 20
< Last-Modified: Wed, 11 Jul 2018 10:10:50 GMT
< Connection: keep-alive
< ETag: "5b45d7aa-14"
< Accept-Ranges: bytes
< 
liuquanhao is best.
* Connection #0 to host haha.ooo left intact

可以看到* Rebuilt URL to: http://haha.ooo/,curl或者浏览器会自己在后面添加/

好了,现在只需要把网页放到html/下,就可以放线上运行了。那就玩真格的,我买了一台服务器,现在把/etc/host中的127.0.0.1 haha.ooo这条记录删了,然后在域名解析里配置一条A记录到我的服务器。

img1

然后我重新在我的服务器编译一次,以为系统环境依赖版本有些不一致,我电脑编译的在服务器里不一定能运行。

因为我的服务器运行的是centos,为了编译nginx,依然是需要先安装编译环境,下载nginx和pcre源码包,然后解压编译:

[root@YUN83222144 ~]# yum -y groupinstall "Development Tools"
[root@YUN83222144 ~]# yum -y install zlib-devel
[root@YUN83222144 ~]# wget http://nginx.org/download/nginx-1.14.0.tar.gz
[root@YUN83222144 ~]# wget https://ftp.pcre.org/pub/pcre/pcre-8.41.tar.bz2
[root@YUN83222144 ~]# tar -xvf nginx-1.14.0.tar.gz
[root@YUN83222144 ~]# tar -xvf pcre-8.41.tar.bz2
[root@YUN83222144 ~]# cd nginx-1.14.0
[root@YUN83222144 nginx-1.14.0]# ./configure --with-pcre=../pcre-8.41
[root@YUN83222144 nginx-1.14.0]# make

然后新建一个server目录,把编译好的nginx放进去,然后配置好目录必须的文件:

[root@YUN83222144 server]# pwd
/root/server
[root@YUN83222144 server]# tree
.
├── conf
│   └── nginx.conf
├── html
│   └── index.html
├── logs
└── nginx

4 directories, 4 files
[root@YUN83222144 server]# cat html/index.html 
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>哈哈,哦哦哦</title>
</head>
<body>
<p>liuquanhao is best.</p>
<body>
</html>

还有一点,有些服务器默认开了防火墙,会阻挡ssh以外的所有端口,http的80也被阻挡了,所以即使运行了nginx也无法用你的电脑通过浏览器访问,这个时候需要添加端口,具体的方法要看你的iptables还是firewalld,你需要配置好。如果你是阿里云或者aws之类的云服务,可能还需要在云管理平台为你的server添加对应网络规则。我的是firewalld,所以看看我的环境:

[root@YUN83222144 server]# firewall-cmd --state
running
[root@YUN83222144 server]# firewall-cmd --get-active-zones
public
  interfaces: eth0

我服务器的firewalld正在运行,zone是public环境。

[root@YUN83222144 server]# firewall-cmd --info-zone=public
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: ssh dhcpv6-client http
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 
	
[root@YUN83222144 server]# firewall-cmd --info-service=http
http
  ports: 80/tcp
  protocols: 
  source-ports: 
  modules: 
  destination: 

我的public里面已经添加了http这个service,它配置了80/tcp端口,就是http端口。

好了,现在打开nginx服务器:

[root@YUN83222144 server]# ./nginx -p .
[root@YUN83222144 server]# ss -anpt | grep nginx
LISTEN     0      128          *:80                       *:*                   users:(("nginx",pid=18474,fd=6),("nginx",pid=18473,fd=6))

现在用浏览器访问http://haha.ooo/,访问成功。

liuxu:~$ curl -lv http://haha.ooo/
*   Trying 181.xxx.xxx.xxx...
* TCP_NODELAY set
* Connected to haha.ooo (181.xxx.xxx.xxx) port 80 (#0)
> GET / HTTP/1.1
> Host: haha.ooo
> User-Agent: curl/7.58.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.14.0
< Date: Thu, 12 Jul 2018 02:36:12 GMT
< Content-Type: text/html
< Content-Length: 147
< Last-Modified: Thu, 12 Jul 2018 02:35:38 GMT
< Connection: keep-alive
< ETag: "5b46be7a-93"
< Accept-Ranges: bytes
< 
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>哈哈,哦哦哦</title>
</head>
<body>
<p>liuquanhao is best.</p>
<body>
</html>

* Connection #0 to host haha.ooo left intact

知识共享许可协议    鄂ICP备 15002452号-5    鄂公网安备 42088102000048号