作者:桂花年糕仔,未经允许,不得转载!

持续更新中

文章目录

  • 前言
  • 第1章 环境搭建
  • 第2章 上传测试及自写API
    • 2.1 上传测试
    • 2.2 自写API
    • 2.3 上传的同时更新日志文件
  • 第3章 redis数据库
    • 3.1 介绍
    • 3.2 安装
    • 3.3 修改配置文件
    • 3.4 Redis Desktop Manager
    • 3.5 中毒体验
    • 3.6 修复木马
  • 第4章 MYSQL的安装
    • 4.1 MYSQL下载
    • 4.2 MYSQL安装
    • 4.3 MYSQL登录及修改密码
    • 4.4 MYSQL设置远程访问(Navicate)
    • 4.5 MYSQL修改字符编码
  • 第5章 shell脚本
  • 第6章 Nginx部署
    • 6.1 Nginx下载及安装
    • 6.2 Nginx配置及优化
    • 6.3 Nginx测试
    • 6.4 Nginx反向代理
    • 6.5 Nginx负载均衡
    • 6.6 Nginx总结
  • 第7章 FastCGI
    • 7.1 FastCGI和Spawn-fcgi的安装
    • 7.2 FastCGI和Spawn-fcgi的作用
    • 7.3 三者的配置
  • 8 实现文件上传的操作
    • 8.1 基本流程
    • 8.2 部署web界面
    • 8.3 文件上传(阶段一)
    • 8.4 文件上传(阶段二)

前言

该项目是用C和C++写的,涉及到很多知识点,还没写完,是一个拓展视野的好项目!

第1章 环境搭建

说明,本人租用的是阿里云服务器,其实用本地虚拟机也可以,结合https://blog.csdn.net/qq_43647359/article/details/105645615(FastDFS 的安装、使用、踩坑过程)和B站的一个视频 https://www.bilibili.com/video/BV1gh411m7tG?p=6(FastDFS分布式文件系统精品教程)可以将 TrackerStorage运行起来
一直可以到这一步

fdfs_monitor /etc/fdfs/client.conf   %向客户端返回storage的信息

第2章 上传测试及自写API

2.1 上传测试

fdfs_upload_file /etc/fdfs/client.conf 捕获.PNG
/*通过启动客户端,将捕获.png文件,上传至storage.
要注意,当前路径包含捕获.PNG
fastdfs会通过算法,将捕获.PNG转换成一个唯一的文件名。如下所示*/

别看这个操作好像很鸡肋,如果每个人都有一个fastDFS,那么就可以集体上传了,或许百度网盘这个客户端自身就是集成了fastDFS这种类型的功能,只不过是作为client的角色!

查看我们的文件到底上传到哪了,可以发现在这个位置,自动帮我们保存了,还能发现存储路径和上一张图名字很像。

2.2 自写API

这时候,我们需要做一件事,就是自己封装一个文件上传的API,然后用main函数调用。当然了,一些头文件用的还是fast DFS自带的,主要有以下几个模块,fdfs_api.hfdfs_api.cmain.c
代码如下:

//fdfs_api.h1 #ifndef _FDFS_API_H2 #define _FDFS_API_H3 int fdfs_upload_file(const char* conf_file,const char* myfile,char* file_id);//函数声明4 #endif
//fdfs_api.c
1 #include <stdio.h>2 #include <stdlib.h>3 #include <string.h>4 #include <string.h>5 #include <errno.h>6 #include <sys/types.h>7 #include <sys/stat.h>8 #include "fdfs_client.h"9 #include "fastcommon/logger.h"10 11 int fdfs_upload_file(const char* conf_file,const char* myfile,char *file_id)13 {14     char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];15     ConnectionInfo *pTrackerServer;16     int result;17     int store_path_index;18     ConnectionInfo storageServer;19 20     //通过客户端配置文件初始化一些数据21     //result中包含了客户端的一些信息22     if ((result=fdfs_client_init(conf_file)) != 0)23     {24         return result;25     }26     // 通过从配置文件中读出的数据,连接追踪器trackker27     // 通过得到的地址可以访问追踪器28     pTrackerServer = tracker_get_connection();29     //如果追踪器连接不上30     if (pTrackerServer == NULL)31     {32         fdfs_client_destroy();  //释放客户端33         return errno != 0 ? errno : ECONNREFUSED;34     }35 36     *group_name = '\0';37 38     //通过tracker得到存储节点信息39     if ((result=tracker_query_storage_store(pTrackerServer, \40                     &storageServer, group_name, &store_path_index)) != 0)41     {42         fdfs_client_destroy();43         fprintf(stderr, "tracker_query_storage fail, " \44             "error no: %d, error info: %s\n", \45             result, STRERROR(result));46         return result;47     }48 49     //文件上传50     result = storage_upload_by_filename1(pTrackerServer, \51             &storageServer, store_path_index, \52             myfile, NULL, \53             NULL, 0, group_name, file_id);54     if (result == 0)55     {56         printf("%s\n", file_id);57     }58     else59     {60         fprintf(stderr, "upload file fail, " \61             "error no: %d, error info: %s\n", \62             result, STRERROR(result));63     }64 65     tracker_close_connection_ex(pTrackerServer, true);66     fdfs_client_destroy();67 68     return result;69 }70 
//main.c1 #include<stdio.h>2 #include<stdlib.h>3 #include<unistd.h>4 #include"fdfs_api.h"5 6 int main(int argc,char* argv[])7 {8     char fileid[1024]={0};9     //调用第4行头文件中的函数,参数1是配置文件的名字,//参数2是你要上传的文件名,在启动的时候通过main函数传入,//参数3是一个返回值,我们提前定义了一个数组用于接收10     fdfs_upload_file("/etc/fdfs/client.conf",argv[1],fileid);11     printf("fileID = %s\n",fileid);12 }

编译的过程中,当我们输入:gcc fdfs_api.c main.c 会出现fdfs_client.h:没有那个文件或目录的错误,是因为我们没有关联这些头文件的路径,这时候,我们包含这个目录gcc fdfs_api.c main.c -I /usr/include/fastdfs/,又会出现有些函数找不到定义的情况,这是因为我们缺动态库,需要指定动态库。再次输入gcc fdfs_api.c main.c -I /usr/include/fastdfs/ -lfdfsclient,发现不会报错了。这时候我们输入gcc fdfs_api.c main.c -I /usr/include/fastdfs/ -lfdfsclient -o app,用于获取一个app可执行文件。
接下来执行可执行文件

./app a.out   //a.out是我们要输入的参数2,即要上传的文件名

上一段的过程如下:

2.3 上传的同时更新日志文件

可以看到上面一张图中,控制台输出了两行信息,其实,我们有时候不需要,如果每次上传之后,log日志文件中会有记录,那么我们想看的时候,在log日志中看不是更方便吗!下面给出了log日志的API,一个.c文件,一个.h文件。

//make_log.h
#ifndef  _MAKE_LOG_H_
#define  _MAKE_LOG_H
#include "pthread.h"int out_put_file(char *path, char *buf);
int make_path(char *path, char *module_name, char *proc_name);
int dumpmsg_to_file(char *module_name, char *proc_name, const char *filename,int line, const char *funcname, char *fmt, ...);
#ifndef _LOG
#define LOG(module_name, proc_name, x...) \do{ \dumpmsg_to_file(module_name, proc_name, __FILE__, __LINE__, __FUNCTION__, ##x);\}while(0)
#else
#define LOG(module_name, proc_name, x...)
#endifextern pthread_mutex_t ca_log_lock;#endif
//make_log.c
#include<string.h>
#include"make_log.h"
#include<pthread.h>
{char mesg[4096]={0};char buf[4096]={0};char filepath[1024] = {0};time_t t=0;//struct file_path *path;//path = (struct file_path*)paths;now = localtime(&t);va_end(ap);make_path(filepath, module_name, proc_name);pthread_mutex_lock(&ca_log_lock);out_put_file(filepath, buf);pthread_mutex_unlock(&ca_log_lock);return 0;
}//写入内容
int out_put_file(char *path, char *buf)
{fd = open(path, O_RDWR | O_CREAT | O_APPEND, 0777);fprintf(stderr, "write error!\n");//write(fd, "\n", 1);}return 0;
}
//创建目录
int make_path(char *path, char *module_name, char *proc_name)char y_dir[1024] = {0};char m_dir[1024] = {0};char d_dir[1024] = {0};time(&t);now = localtime(&t);sprintf(third_dir, "%s/%s", second_dir, module_name);sprintf(y_dir, "%s/%04d/", third_dir, now -> tm_year + 1900);sprintf(m_dir, "%s/%02d/", y_dir, now -> tm_mon + 1);sprintf(d_dir,"%s/%02d/", m_dir, now -> tm_mday);if(access(top_dir, 0) == -1) {if(mkdir(top_dir, 0777) == -1) {fprintf(stderr, "create %s failed!\n", top_dir);} else if(mkdir(second_dir, 0777) == -1) {fprintf(stderr, "%s:create %s failed!\n", top_dir, second_dir);} else if(mkdir(third_dir, 0777) == -1) {fprintf(stderr, "%s:create %s failed!\n", top_dir, third_dir);} else if(mkdir(y_dir, 0777) == -1) {}} else if(access(second_dir, 0) == -1) {if(mkdir(second_dir, 0777) == -1) {fprintf(stderr, "create %s failed!\n", second_dir);} else if(mkdir(third_dir, 0777) == -1) {fprintf(stderr, "%s:create %s failed!\n", second_dir, third_dir);} else if(mkdir(y_dir, 0777) == -1) {fprintf(stderr, "%s:create %s failed!\n", second_dir, y_dir);} else if(mkdir(m_dir, 0777) == -1) {fprintf(stderr, "%s:create %s failed!\n", second_dir, m_dir);}} else if(access(third_dir, 0) == -1) {if(mkdir(third_dir, 0777) == -1) {fprintf(stderr, "create %s failed!\n", third_dir);} else if(mkdir(y_dir, 0777) == -1) {fprintf(stderr, "%s:create %s failed!\n", third_dir, y_dir);} else if(mkdir(m_dir, 0777) == -1) {fprintf(stderr, "%s:create %s failed!\n", third_dir, m_dir);}} else if (access(y_dir, 0) == -1) {if(mkdir(y_dir, 0777) == -1) {fprintf(stderr, "create %s failed!\n", y_dir);} else if(mkdir(m_dir, 0777) == -1) {fprintf(stderr, "%s:create %s failed!\n", y_dir, m_dir);}} else if (access(m_dir, 0) == -1) {if(mkdir(m_dir, 0777)) {fprintf(stderr, "create %s failed!\n", m_dir);}}//printf("path:%s\n", path);return 0;}

我们在上传文件的功能中,将上传成功以及上传失败的信息都加入到了log日志当中。LOG的前两个参数只是路径名

第3章 redis数据库

3.1 介绍


3.2 安装

进入官网:http://redis.io,下载3.2.8版本,现在已经出到6.0+版本了,由于我们是学习,不需要那么高版本。

下载好之后,通过finalshell上传到云服务器的相应文件夹中,然后执行以下命令,进行解压缩,安装

tar -zxvf redis-3.2.8.tar.gz  解压缩
cd redis-3.2.8
make
sudo make install

make的过程中发现了很有意思的东西:

redis启动命令:redis-server

重开一个窗口,输入redis-cli命令去链接redis,因为原先启动了redis服务的那个窗口会阻塞。

通过set key valuemset key value命令去创建单键值对以及批量创建键值对。key *命令可以查看所有的key
redis的一些命令还可以对已经存储了的键值对进行加减(数值才可以)、拼接的操作,这个具体查看相应的命令即可。

3.3 修改配置文件

通过修改redis.conf文件,可以生成log文件,可以让其他电脑连接这个数据库。

3.4 Redis Desktop Manager

项目中用到了redis,想查询redis中的数据,一直想找一个可视化工具,今天发现了Redis Desktop Manager,试用了一下,很好用。下载链接:http://www.xue51.com/soft/5385.html(别进这个链接下载,有毒,下面先给正常情况下的效果图)
这里要注意修改redis.conf中的一些东西,还要注意开放云服务器的相应端口,否则用这个软件连不上。

所有都配置好后,可以测试一下,通过在云端修改数据库,然后刷新这个redis管理工具,可以看到数据库的变动

3.5 中毒体验

我真是想揍它的,这个网址下载的软件有毒,搞得我云服务器CPU占有率100%,去网上查了一下是说中了病毒crypto和pnscan病毒

3.6 修复木马

后面百度了一下,说是中了pnscan 挖矿蠕虫病毒,由于我云服务器也没配置什么东西,看了一下修复操作挺复杂的,索性就重置了一下服务器,后面还特意把redis.conf中的允许其它用户连接改成了仅允许本级访问,还特地加了redis-cli密码,还把redis的端口号也给改了。我就不信以后还会中病毒。
redis.conf中随意一个位置加入requirepass ***,***指的是你要设置的密码,redis的启动密码。从下图中可以发现,单单通过端口号去链接可以连上,但是无法使用命令,所以我们在登陆时,不仅要用-p指定端口号,还需要-a加上登陆密码

ps aux | grep redis-server  //查看redis进程

第4章 MYSQL的安装

4.1 MYSQL下载

首先这个安装过程还是有点复杂的,不过照着这个步骤来,不会错。建议安装5.7.20版本的MYSQL。高版本的MYSAL发生了问题也不好解决(用的人不多)。
第一步:官网下载https://downloads.mysql.com/archives/community/,也可以直接百度,进入MYSQL首页,然后在最下方找到社区版

第二步:进入历史版本,选择5.7.20以及红帽系统,再点击第一个下载,第一个安装的最全

4.2 MYSQL安装

第三步:下载好安装包后,通过finalshell管理工具上传至云服务器上,和其它软件一样,我们安装在了usr/local/目录下
第四步:要安装首先得把解出到一个目录,使用tar –xvf 包名 –C 目录名
依次执行以下命令:

mkdir mysql
tar -xvf mysql-5.7.20-1.el7.x86_64.rpm-bundle.tar -C mysql
cd mysql

进入目录后会看到如下文件
这个包里边除了服务端和客户端外,还有一些依赖库以及拓展包,我们只要安装服务端和客户端即可。不过安装这些包都有依赖关系,再没有安装依赖包之前安装软件会报错,所以一般都是以下顺序安装:

sudo rpm -ivh mysql-community-common-5.7.20-1.el7.x86_64.rpm
sudo rpm -ivh mysql-community-libs-5.7.20-1.el7.x86_64.rpm
sudo rpm -ivh mysql-community-client-5.7.20-1.el7.x86_64.rpm
sudo rpm -ivh mysql-community-server-5.7.20-1.el7.x86_64.rpm
sudo rpm -ivh mysql-community-devel-5.7.20-1.el7.x86_64.rpm
  • 执行上面命令的过程中可能会报错: mariadb-libs 被 mysql-community-libs-8.0.13-1.el7.x86_64 取代
    一个命令:yum remove mysql-libs解决,即清除之前安装过的依赖即可。参考于https://blog.csdn.net/ypp91zr/article/details/84801204

  • 还有可能出现 mysql-community-client(x86-64) >= 5.7.9 被 mysql-community-server-5.7.30-1.e64需要的 错误。
    出现该问题的原因可能为,在安装MYSQL之前,删除了mariadb,导致部分依赖找不到,通过以下指令重新安装mariadb。参考于https://blog.csdn.net/weixin_44311939/article/details/106189130

yum install mariadb-server mariadb
systemctl start mariadb
systemctl enable mariadb
  • 最后还有一种方法可以解决,卸载刚刚安装好的软件,使用以下命令查看当前安装mysql情况,查找以前是否装有mysql,参考于https://www.cnblogs.com/nicknailo/articles/8563456.html

  • rpm -qa|grep -i mysql会显示之前安装了:

    MySQL-client-5.5.25a-1.rhel5

    MySQL-server-5.5.25a-1.rhel5

    • 停止mysql服务、删除之前安装的mysql,删除命令:rpm -e –nodeps 包名
    • rpm -ev MySQL-client-5.5.25a-1.rhel5
      rpm -ev MySQL-server-5.5.25a-1.rhel5


第五步:安装完之后,我们启动mysql,启动命令为sudo service mysqld start,此时可以用ps –ef | grep mysqld看到mysql的守护进程mysqld

4.3 MYSQL登录及修改密码

第六步登录:mysql.5.7的mysql默认密码跟以往不同的是,默认mysql中root用户密码会写到log文件里边,我们要从log文件中找到默认密码,登录上去。

cd /var/log/    //进入log文件目录
vim mysqld.log  //查看默认的密码

可以看到如图所示的默认密码
输入mysql –uroot –p密码进行登录
第7步:修改密码
方法一,在还未连接时,直接修改,可以修改成功,但是会提示警告,因为通过网络传输修改密码不安全

mysqladmin -u root -p password "要修改的密码"Enter password: 【输入原来的密码】

方法二,通过登录mysql系统

 mysql -uroot -pEnter password: 【输入原来的密码】mysql>use mysql;mysql> update user set password=passworD("要修改的密码") where user='root';mysql> exit;

至此,就结束了,通过mysql -uroot -p,再输入刚刚修改的密码,即可验证是否成功。

4.4 MYSQL设置远程访问(Navicate)

连接上MYSQL,然后输入以下命令,开启远程连接

mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '登陆密码' WITH GRANT OPTION;flush privileges   //类似于刷新操作

打开Navicat软件进行连接
连接成功

4.5 MYSQL修改字符编码

连接上mysql数据库之后,我们可以查看当前的字符集,命令为\s,如下图所示:一开始的时候图中圈出的两个是拉丁,我们需要更改为utf8。

更改方式如下,打开my.cnf配置文件,配置文件在/etc/mysql/my.cnf,有些在直接就在/etc目录下。

cd /etc/
vim my.conf
将这两行代码加入到[mysqld]下方
character-set-server=utf8
collation-server=utf8_general_ci


保存文件后,重启mysql,命令如下

service mysqld stop    停止
service mysqld start   重启

再次连接mysql,输入\s,查询是否修改成功。

第5章 shell脚本

shell脚本通常以.sh 为后缀名,例如通过 vim test.sh命令创建了一个名为test的脚本。其中shell脚本里面通常编写的是一些命令。
例如:在test.sh中写入以下两行命令

ls -l  显示当前文件夹内所有目录文件的相关信息
echo "你好"

保存退出以后通过./test.sh命令可以执行shell脚本,值得注意的是,再输入命令之前我们还需要赋予test.sh文件一定的权限,否则无法运行

chmod u+x  文件名.sh
或者用
chmod 777  文件名.sh

然后再输入./test.sh命令就可以执行了,(补充:sh test.sh命令也可以)效果如下

第6章 Nginx部署

6.1 Nginx下载及安装

nginx下载地址:http://nginx.org/download/nginx-1.19.4.tar.gz,下载好之后发送到云服务器的/usr/local/文件夹

cd /usr/local/srctar zxvf nginx-1.19.4.tar.gz     解压yum install -y gcc zlib zlib-devel openssl openssl-devel pcre
//安装gcc编译环境
//安装zlib库,zlib库提供了很多压缩和解压缩的方式
//安装套接字密码库,它是一个强大的套接字层密码库,nginx不仅支持http还支持https(即ssl协议上传输http)
//pcre正则表达式cd /usr/local/nginx-1.19.4/./configure
make
make installcd /usr/local/nginx/sbin
./nginx                   //启动
ps aux |grep nginx        //查看进程是否启动了

在网址栏输入自己的云服务器ip地址,可以看到能够成功访问
重写配置文件后,需要重启nginx服务器。
重启命令./nginx -s reload
注意,在其他位置启动nginx必须加上绝对路径/usr/local/nginx/sbin,因为nginx在安装的时候没有加入到path路径中。

6.2 Nginx配置及优化

由于每次启动nginx,如果不是在/usr/local/nginx/sbin目录下,就必须加上绝对路径,即用该命令去启动nginx:/usr/local/nginx/sbin/./nginx,会比较麻烦,因此我们可以通过创建软连接的方式去直接使用nginx的命令去启动nginx。
具体原理如下:

  • 在linux中,lscd等都是命令,通过which ls,可以发现ls命令在 /usr/bin/ls中,而通过echo $PATH命令,我们可以看到,linux的环境变量中包含了如下路径/usr/local/sbin: /usr/local/bin: /usr/sbin: /usr/bin: /root/bin,其中就包含了ls的所在路径,因此我们可以理解为,通过添加路径到PATH中,我们可以直接使用nginx这种简洁的命令去启动nginx。

step1:先关闭正在运行的nginx,在**/usr/local/nginx/sbin**目录中先输入./nginx -s stop
step2:通过ln -s /usr/local/nginx/sbin/./nginx /usr/bin/nginx命令,将/usr/local/nginx/sbin/./nginx这一操作加入到/usr/bin/目录中,并命名为nginx,至此,我们在任意位置只需要输入nginx,即可启动nginx服务器。
并且现在关闭nginx的命令也只需要输入nginx -s stop,此外nginx -s quit命令会更柔和一点,会先执行完手中的活,再退出nginx。


注意,step2中的这一操作在很多地方可用来提升办公效率
Nginx官方参考文档:http://nginx.org/en/docs/
淘宝团队翻译版本:http://tengine.taobao.org/nginx docs/cn/cocs/需要看源码再深入了解,一般是运维才需要了解。
配置文件的位置/usr/local/nginx/conf

6.3 Nginx测试

第一步:将测试的文件html1.tar.gz上传至云服务器。输入tar zxvf html1.tar.gz进行解压缩。解压缩完成后,会自动创建一个demo的目录,目录下有相应的文件
第二步:修改配置文件,在这里我们加入了两个界面进行测试。
在网址栏分别输入云服务器的ip地址,以及云服务器ip地址/second.html,即可访问下面两个页面。

由上面两个静态页面可以得出,用户也可以随时添加其它静态页面,ip地址后面的/指的是资源文件。如192.168.22.12/second.html,输入这个网址,会在资源文件的根目录中找到second.html的资源。又如192.168.22.12/test/index.html则表示会在资源文件的根目录中找到test目录下的index.html的资源。


关于配置文件中,localtion的一些用法日后可以详细探索
补充1,上网通过域名连接到ip地址的方式如下图所示:
补充2,host文件也是通过解析的方式,不过是在本地,访问谷歌什么的,其实并不需要VPN,只需要在host文件中指定解析ip,这个具体还得查阅,没去深究。
补充3,反向代理的前提:有多台web服务器,因为要去做负载均衡,如果只有一台,直接链接就可以了

6.4 Nginx反向代理

必要条件

windows下nginx的配置文件nginx.conf中要加入的配置项

#设置两个Linux服务器的反向代理
# 先配置luffy
upstream luffy.web{       server 192.168.82.251:80;
}
# 再配置robin
upstream robin.web{server 192.168.82.253:80;
}
#配置要代理的服务器信息
# 先配置luffy
# luffy - 192.168.82.251
server{# 监听的端口listen 80;# 通过什么域名去访问当前的web服务器server_name luffy.com;location / {# 设置代理proxy_pass http://luffy.web;}}# 配置robin
# robin - 192.168.82.253
server{# 监听的端口listen 80;# 通过什么域名去访问当前的web服务器server_name robin.com;location / {# 设置代理proxy_pass http://robin.web;}}

具体原理:
反向代理服务器通过监听80端口,查看80端口传来的信息是通过什么域名去访问当前的web服务器的。
举例,监听到当前80端口,传来了一个访问luffy.com的信息,通过定位server_name luffy.com,查看location中的代理http://luffy.web,再通过http://luffy.web找到upstream中http://luffy.web最终指向的真实ip192.168.82.251:80


工作流程

  • 通过浏览器访问server模块中的server_name对应的域名
  • 服务器去找location /
  • 需要在里面设置代理:proxy_pass +url
  • url自己编一个就可以
  • 通过这个url的名字去找到upstream模块
  • 找到之后,去访问该模块中server对应的ip地址

6.5 Nginx负载均衡

说明负载均衡是在反向代理的基础上进行的。
和6.4反向代理不同的是,负载均衡不需要那么多server,只需要一个就行了。

#在反向代理的基础上设置两个Linux服务器的负载均衡
# 配置linux.web
upstream linux.web{       server 192.168.82.251:80;  #什么都没设置,那默认两者的权重是一样的server 192.168.82.253:80;  #nginx通过轮询的方式将请求传递给两者#下面这种方式为设置权重的方式  5:1   注意weight的最小值为1# server 192.168.82.251:80 weight=5;# server 192.168.82.253:80 weight=1;
}# 配置要代理的服务器信息
server{# 监听的端口listen 80;# 通过什么域名去访问当前的web服务器server_name localhost;   location / {# 设置代理proxy_pass http://linux.web;}}
  • 入口:server模块里面server_name对应的域名,也就是刚面写的localhost,这个server_name对应的域名没有要求,可以随意取。
  • 配置好之后重启,在网址栏输入localhost,nginx会进入到location /,发现是一个代理,里面的proxy_pass有一个url,然后通过url的名字去找upstream,找到之后,则会根据权重将用户的请求转发给251或者253ip地址中的其中一个。

6.6 Nginx总结

1.nginx作为web服务器

1. 优缺点

优点

  1. 部署简单
  2. 效率高
  3. 热部署

缺点

  1. 只能在nginx上边部署静态网页
  2. 动态网页?
    2.1 要登陆
    2.2 例如给定网址http://1.1.1.1/login.html
    2.3 用户在这个网址需要输入账号密码进行登录,但是nginx无法直接处理登陆的数据
    2.4 如果用户要验证,则需要在nginx中调用第三方模块去处理

如何处理
使用CGI去处理
我们需要做的事是调用CGI接口去完成数据处理(涉及http协议)


第7章 FastCGI

7.1 FastCGI和Spawn-fcgi的安装

第一步:安装FastCGI
首先解压FastCGI,
然后cd进入解压后的文件夹,
执行./configure命令,
继续执行make命令,这时候会发现有报错。

错误原因:C++版本迭代的时候,将EOF的定义换到了另一个头文件中。
解决方法:在fcgio.cpp中加入相关的头文件,首先我们要找到这个fcgio.cpp
查找命令为find ./ -name "fcgio.cpp"

然后vim fcgio.coo,加入#include<stdio.h>头文件。
然后执行以下两步:
make
make install
第二步:安装Spawn-fcgi
这个简单,执行以下四个步骤

  • 解压缩:tar zxvf spawn-fcgi-1.6.4.tar.gz
  • 进入文件夹,./configure
  • make
  • make install

7.2 FastCGI和Spawn-fcgi的作用

7.3 三者的配置

第一步:(配置nginx.conf)
当网页需要进行如登录注册这种光靠nginx无法完成的行为时,需要借助fastCGI模块进行配置,首先要vim nginx.conf,在nginx.conf中加入如下的代码:

#处理一个指令 test#url:http://106.15.34.47/test   用户访问的url#但是nginx自身无法处理指令,所以要配置fastCGI模块location /test{#配置fastCGI模块fastcgi_pass localhost:9001;#包含一个配置文件和nginx.conf一个目录include fastcgi.conf;}

注意: 上面的localhost改成127.0.0.1或者你本机的ip都行。不过这里还有要注意的:
如果nginx.conf中写的是127.0.0.1或者localhost,那么在spawn-fcgi -a IP -p 端口 -f fastcgi程序命令中的IP就要填127.0.0.1,如果nginx.conf中写的是服务器的IP,那么在spawn-fcgi -a IP -p 端口 -f fastcgi程序命令中的IP就要填服务器的IP
将要处理的数据发送到9001端口,9001端口对应一个进程,该进程可以收到nginx发过来的数据。


第二步:(编写fcgi程序)
到这里nginx就算配置好了,然后我们需要编写一个fcgi程序,这个程序是用来被spawn-fcgi调用的。
我们首先使用cp echo.c ~命令,将/usr/local/fcgi-2.4.1-SNAP-0910052249/examples目录中的示例文件echo.c拷贝到根目录,然后执行以下命令去编译他:

gcc echo.c   #执行这句话会报错,提示缺少动态库gcc echo.c -lfcgi  #-l指的是连接动态库,fcgi指的是fcgi.so执行完之后,会得到一个a.out文件

但是当我们去执行这个a.out文件时,会报错,如下(未找到动态库)

./a.out: error while loading shared libraries: libfcgi.so.0: cannot open shared object file: No such file or directory


解决方法:
首先,我们检查这个动态库是否存在:

find  /usr/local/lib -name libfcgi.so.0执行完后,发现动态库是在的,在以下目录
/usr/local/lib/libfcgi.so.0然后我们执行以下操作
vi /etc/ld.so.conf  打开文件
在下面加一行/usr/local/lib
执行 ldconfig命令

如下图所示


补充:有时缺少动态库还需要执行以下操作
碰到的一个问题:在执行命令时出现了这样的错误

后面发现原因处在了出在了缺少动态库:libhiredis.so.0.13 => not found
我先是用find命令查找这个库,发现并没有找到这个库,然后看到一篇博客,说要下载:执行以下命令

wget https://github.com/redis/hiredis/archive/v0.13.3.tar.gz
tar -xzvf v0.13.3.tar.gz
cd  hiredis-0.13.3
make -j4
make -j4 install
ldconfig

但是我发现执行完上述命令后还是不行,还需要添加下两个命令。

ln -s /usr/local/lib/libhiredis.so.0.13 /usr/lib/libhiredis.so.0.13
ln -s /usr/local/lib/libhiredis.so.0.13 /usr/lib64/libhiredis.so.0.13

现在再执行ldd upload就没有这一类问题了

第三步:运行
首先,我们在静态网页前端代码中这样设置,将method设置为get,后面的action设置为你服务器的ip地址和test请求,这里的意思相当于你在网页上填好了你的个人信息,然后点击提交,那么就会触发get请求,然后指向test请求。如下图所示。

然后我们要重启一下nginx,因为刚刚修改了nginx.conf,如果不重启,我们提交表单的时候可能不生效,就会显示如下的界面。

重启命令为:nginx -s reload
最后, 我们只需要输入以下命令即可spawn-fcgi -a 127.0.0.1 -p 9001 -f ./a.out,然后在网页填写相应的信息再提交即可,如下图所示:

 -a - IP: 服务器IP地址
 -p - port: 服务器将数据发送到的端口
 -f - cgi程序: spawn-fcgi启动的可执行fastcgi程序


仔细观察上面一幅图可以发现,用户提交的信息主要在这一行QUERY_STRING=username=%E5%B0%8F%E5%BC%BA&phone=15970qweqwe&email=1589221119%40qq.com&date=2021-11-13&sex=female&class=3&rule=on,那么我们只需要想办法提取就可以获得我们想要的信息。


如果把静态网页前端代码中的method设置为post,那么会得到这样的界面。会发现更简洁了
fastcgi.conf中常用环境变量:
○ QUERY_STRING: 请求的资源, 请求行的第二部分
○ REQUEST_METHOD: 请求方法, get/post
○ CONTENT_TYPE: 文件类型
○ SCRIPT_NAME: 处理的指令, nginx中配置cgi的时候用
○ REQUEST_URI: 浏览器中请求的资源, 不包括IP+port


8 实现文件上传的操作

8.1 基本流程

  1. 将上传的前端代码文件夹zyupFile拷贝到ngixn安装目录
  2. 查看上传文件对应的html文件
    ○ 找到数据提交的位置(nginx需要配置的指令 - /upload)
  3. 修改nginx配置文件
    ○ 添加一个location /upload{
    fastcgi_pass IP:port;
    include fastcgi.conf;
    }
  4. 重新加载nginx配置文件
    ○ nginx -s reload
  5. 编写一个fastcgi程序
     将上传文件内容保存到web服务器
     调用fastdfs api将文件上传到fastdfs存储节点上
     得到一文件ID
     将文件和对应的fastdfs返回的文件ID存储到mysql数据库
     将上传之后的文件从web服务器删除

8.2 部署web界面

  • 前端html文件解释
  • nginx.conf配置(配置完之后记得重启)
  • 在浏览器以两种方式输入相应的url,然后观察效果,可以看到,配置完之后,不论是根目录还是二级目录都能访问,效果如下:

8.3 文件上传(阶段一)

在阶段一,我们首先看一下文件上传过程中,会有哪些信息。

  • 首先在html文件中查看上传的请求
  • 会发现上传时会用到upload请求,这时候我们需要在nginx.conf中配置upload请求。
  • 我们设置了一个8002端口用于负责upload请求,然后通过spawn-fcgi -a 127.0.0.1 -p 8002 -f ./a.out命令启动了a.out程序用于监听8002端口,一旦有请求过来,那么就会执行a.out程序,a.out程序的作用是将上传的文件信息打印在网页上,如下图所示,我们上传了一张图片,点击上传操作时,a.out程序就会显示如下信息。
    其中图片的信息夹在两行语句之间,如下图所示紫色的为文件名,红色的为文件的自身信息
------WebKitFormBoundaryHnkjpSB2GTtBWlrg
文件名
文件类型
文件的数据
------WebKitFormBoundaryHnkjpSB2GTtBWlrg

这一节,我们主要演示了图片在上传时,我们将其信息打印出来,主要用到的是a.out程序也就是echo.c.
那么思考一下,如何将图片上传到服务器呢?
其实就是写一个程序,将------WebKitFormBoundaryHnkjpSB2GTtBWlrg
之间的内容也就是文件的名称和信息写到fastDFS即可,有了名称上传到fastDFS我们还能得到一个id,然后将名称和id存到数据库中,这时候就能实现下载的操作。这就是我们在阶段二要做的事。

8.4 文件上传(阶段二)

第一步:
fastdfs-nginx-module_v1.16.tar.gz文件上传到云服务器上,解压完毕后路径下,会有以下文件。

第二步:(注意这一步是错误的,下面会修正)

这里需要重新下一个1.10.1版本的nginx,用于部署在storage节点上,目的是为了方便下载阶段,1.10.1版本以上可能会报错。
nginx1.10.1的下载链接:https://nginx.org/download/nginx-1.10.1.tar.gz
下载完毕后,重新编译nginx,此时编译nginx的过程中要将上面出现的pwd路径加入到命令中。
./configure --add-module=/usr/local/fastdfs-nginx-module/src
make
在make之后会报错,说是缺少.h文件,这时候我们需要在makefile中加入这个头文件的路径。
打开Makefile,会发现这个文件只有23行,认真解读会发现其真正的Makefile工作是在objs目录下进行的。
打开真正的Makefile会发现有1000多行,然后我们要在**-I**的位置将刚刚缺少的头文件的路径放进去。
找到刚刚缺失的头文件的路径,一般来说头文件是在/usr/include/目录下的,输入以下命令进行查询:find /usr/include/ -name fdfs_define.h,会发现这个头文件在这个目录下: /usr/include/fastdfs/fdfs_define.h ,把这个路径加入到-I之后继续make,还会发现缺少了一个logger.h文件,按照同样的方法继续执行,但是这里就会发现问题没有解决,反而报错还更多了。

第二步:
所以第二步得重新来,而且后面发现其实不需要在下载一个nginx,直接在原有的nginx的基础上进行配置即可,

  • 删除掉刚刚的两个文件夹,由于是fastdfs-nginx-module中的代码出了问题,考虑到可能是fastdfs-nginx-module和nginx版本不兼容的问题,我们重新下载一个fastdfs-nginx-module
    下载地址:https://github.com/happyfish100/fastdfs-nginx-module。

  • nginx就用之前的,这时候重新执行以下两行代码
    ./configure --add-module=/usr/local/fastdfs-nginx-module-master/src
    make
    最后直接make install

  • 这样就顺利执行了,然后重启nginx -s reload,查看进程ps aux|grep nginx,会发现nginx中的worker进程没有启动,说明还有问题。

  • 找到nginx的log日志,会发现是缺少了mod_fastdfs.conf,这时候,我们需要把mod_fastdfs.conf放在/etc/fdfs目录下。

  • 同时,我们也对mod_fastdfs.conf进行配置,配置和storage.conf差不多。

  • 除此之外,还需要将usr/local/fastdfs/conf/中的http.conf 拷贝到/etc/fdfs/下,从usr/local/nginx-1.19/conf/中的mime.types 拷贝
    到/etc/fdfs/下

  • 配置nginx.conf,加入以下模块:

  • location /group1/M00 {

    root /root/fastdfs/storage/data;
    ngx_fastdfs_module;
    }

  • 把nginx.conf第一行的 #user nobody 换成 user root,否则此后会出现权限不够的问题。

  • 最后重启nginx -s reload即可。

第三步:测试
上面的location指的是将浏览器中的**/group1/M00地址定向为服务器内存中的地址/root/fastdfs/storage/data**,我们服务器上有一张图片,名字为ag8iL2F_X8aAfZhjAAX3_BxwTws124.png
然后在我们的网址栏,输入这个文件对应的名称,就能看到服务器上所存储的图片了。

自己动手写一个网盘?相关推荐

  1. 自己动手写一个 strace

    这次主要分享一下一个动手的东西,就是自己动手写一个 strace 工具. 用过 strace 的同学都知道,strace 是用来跟踪进程调用的 系统调用,还可以统计进程对 系统调用 的统计等.stra ...

  2. 自己动手写一个推荐系统,推荐系统小结,推荐系统:总体介绍、推荐算法、性能比较, 漫谈“推荐系统”, 浅谈矩阵分解在推荐系统中的应用...

    自己动手写一个推荐系统 废话: 最近朋友在学习推荐系统相关,说是实现完整的推荐系统,于是我们三不之一会有一些讨论和推导,想想索性整理出来. 在文中主要以工程中做推荐系统的流程着手,穿插一些经验之谈,并 ...

  3. 手把手教你用 30 分钟搭建一个网盘

    code小生 一个专注大前端领域的技术平台 公众号回复Android加入安卓技术群 本文出处:码匠笔记公众号 Pandownload 下线大家心里都很苦,不过我们还是的重新站起来,于是我研究了一下花了 ...

  4. java 手编线程池_死磕 java线程系列之自己动手写一个线程池

    欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. (手机横屏看源码更方便) 问题 (1)自己动手写一个线程池需要考虑哪些因素? (2)自己动手写 ...

  5. Pandownload 下线了,我花了 30 分钟自己搭建了一个网盘

    点击上方视学算法,选择设为星标 加个"星标★",每日好文必达! 文末包邮送3本技术书! 来源:码匠笔记 阅读文本大概需要 5 分钟 点击「阅读原文」查看pk哥原创精品视频. Pan ...

  6. Pandownload 下线了,我自己花了 30 分钟自己搭建了一个网盘

    点击上方"Python与机器智能",选择"星标"公众号 第一时间获取价值内容 来源:码匠笔记 Pandownload 下线大家心里都很苦,不过我们还是的重新站起 ...

  7. 自己动手写一个印钞机 第四章

    2019独角兽企业重金招聘Python工程师标准>>> 作者:阿布? 未经本人允许禁止转载 ipython notebook git版本 目录章节地址: 自己动手写一个印钞机 第一章 ...

  8. Spring Boot 动手写一个 Start

    我们在使用SpringBoot 项目时,引入一个springboot start依赖,只需要很少的代码,或者不用任何代码就能直接使用默认配置,再也不用那些繁琐的配置了,感觉特别神奇.我们自己也动手写一 ...

  9. 自己动手写一个nodejs的日志生成器

    自己动手写一个nodejs的logger 最近正在边学边用node.js开发个人应用的server,由于有用到websocket相关,想对websocket的通信选择性的做下日志记录,所以萌发了自己动 ...

最新文章

  1. 11月8日学习内容整理:js的引入方式,变量数据类型,运算符,流程控制,函数...
  2. 一文带你学会java的jvm精华知识点
  3. c#3.0系列:Object Initializer 和 Collection Initializer
  4. 生成方法中参数的注释
  5. java设置表格列不可修改_Java DefaultTableModel使单元格不可编辑JTable
  6. 【大事化小,小事化无】的意思和解释
  7. IP通信基础 3月6日
  8. plc编程入门视频教程
  9. 《Adobe Fireworks CS5中文版经典教程》——1.2 工具面板
  10. 类图 顺序图 活动图 状态图 用法和比较
  11. 预测分析·商品评论情感预测-基于PaddleNLP的京东商品评论情感分析竞赛
  12. 4pin oled字模,oled图片编码生成方法
  13. 不能共情你还当什么领导
  14. eclipse mac下常用快捷键
  15. 坐着打游戏也能减肥?1小时=200千卡,竞技游戏、解谜游戏效果更佳
  16. 亚洲第一人,人肉扫码器,怎样提高记忆力
  17. ElasticsearchException: Bulk indexing has failures
  18. 喜茶、奈雪的茶“花式”寻生路
  19. 叮咚小区VS小区无忧
  20. 利用CSS和JS实现抖音超火3d照片墙

热门文章

  1. [转](1条消息) 前端必知:针对高分辨率屏幕的样式优化(转载请删除括号里的内容)
  2. C语言头插法尾插法创建单链表
  3. 史上最全量化交易资源整理
  4. C语言标识符有哪三类
  5. 使用安全模式启动计算机,老司机教你电脑安全模式启动方法
  6. 示波器基本原理1:模拟示波器
  7. uc_client 同步登陆
  8. JMeter基础系列:接口响应时间
  9. 蓝桥杯JAVA-4.常用数据类型
  10. 后端如何编写API文档给到前端?