文章目录作者:桂花年糕仔,未经允许,不得转载!
持续更新中
- 前言
- 第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分布式文件系统精品教程)可以将 Tracker和Storage运行起来
一直可以到这一步
fdfs_monitor /etc/fdfs/client.conf %向客户端返回storage的信息第2章 上传测试及自写API 2.1 上传测试
fdfs_upload_file /etc/fdfs/client.conf 捕获.PNG
别看这个 *** 作好像很鸡肋,如果每个人都有一个fastDFS,那么就可以集体上传了,或许百度网盘这个客户端自身就是集成了fastDFS这种类型的功能,只不过是作为client的角色!
查看我们的文件到底上传到哪了,可以发现在这个位置,自动帮我们保存了,还能发现存储路径和上一张图名字很像。
这时候,我们需要做一件事,就是自己封装一个文件上传的API,然后用main函数调用。当然了,一些头文件用的还是fast DFS自带的,主要有以下几个模块,fdfs_api.h、fdfs_api.c、main.c
代码如下:
//fdfs_api.h 1 #ifndef _FDFS_API_H 2 #define _FDFS_API_H 3 int fdfs_upload_file(const char* conf_file,const char* myfile,char* file_id); //函数声明 4 #endif
//fdfs_api.c 1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 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 // 通过从配置文件中读出的数据,连接追踪器trackker 27 // 通过得到的地址可以访问追踪器 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 = ''; 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: %sn", 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("%sn", file_id); 57 } 58 else 59 { 60 fprintf(stderr, "upload file fail, " 61 "error no: %d, error info: %sn", 62 result, STRERROR(result)); 63 } 64 65 tracker_close_connection_ex(pTrackerServer, true); 66 fdfs_client_destroy(); 67 68 return result; 69 } 70
//main.c 1 #include2 #include 3 #include 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 = %sn",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,即要上传的文件名
上一段的过程如下:
可以看到上面一张图中,控制台输出了两行信息,其实,我们有时候不需要,如果每次上传之后,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...) #endif extern pthread_mutex_t ca_log_lock; #endif
//make_log.c #include#include"make_log.h" #include { 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:%sn", path); return 0; }
我们在上传文件的功能中,将上传成功以及上传失败的信息都加入到了log日志当中。LOG的前两个参数只是路径名
进入官网: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 value 和mset key value命令去创建单键值对以及批量创建键值对。key *命令可以查看所有的key
redis的一些命令还可以对已经存储了的键值对进行加减(数值才可以)、拼接的 *** 作,这个具体查看相应的命令即可。
通过修改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病毒,
后面百度了一下,说是中了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以及红帽系统,再点击第一个下载,第一个安装的最全
第三步:下载好安装包后,通过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
第六步:登录: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 -p Enter 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软件进行连接
连接成功
连接上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/src tar 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 install cd /usr/local/nginx/sbin ./nginx //启动 ps aux |grep nginx //查看进程是否启动了
在网址栏输入自己的云服务器ip地址,可以看到能够成功访问
重写配置文件后,需要重启nginx服务器。
重启命令./nginx -s reload
注意,在其他位置启动nginx必须加上绝对路径/usr/local/nginx/sbin,因为nginx在安装的时候没有加入到path路径中。
由于每次启动nginx,如果不是在/usr/local/nginx/sbin目录下,就必须加上绝对路径,即用该命令去启动nginx:/usr/local/nginx/sbin/./nginx,会比较麻烦,因此我们可以通过创建软连接的方式去直接使用nginx的命令去启动nginx。
具体原理如下:
- 在linux中,ls和cd等都是命令,通过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
第一步:将测试的文件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服务器,因为要去做负载均衡,如果只有一台,直接链接就可以了
必要条件
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地址中的其中一个。
1.nginx作为web服务器
1. 优缺点
优点
- 部署简单
- 效率高
- 热部署
缺点
- 只能在nginx上边部署静态网页
- 动态网页?
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
然后执行以下两步:
make
make install
第二步:安装Spawn-fcgi
这个简单,执行以下四个步骤
- 解压缩:tar zxvf spawn-fcgi-1.6.4.tar.gz
- 进入文件夹,./configure
- make
- make install
第一步:(配置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 基本流程
- 将上传的前端代码文件夹zyupFile拷贝到ngixn安装目录
- 查看上传文件对应的html文件
○ 找到数据提交的位置(nginx需要配置的指令 - /upload) - 修改nginx配置文件
○ 添加一个location /upload{
fastcgi_pass IP:port;
include fastcgi.conf;
} - 重新加载nginx配置文件
○ nginx -s reload - 编写一个fastcgi程序
将上传文件内容保存到web服务器
调用fastdfs api将文件上传到fastdfs存储节点上
得到一文件ID
将文件和对应的fastdfs返回的文件ID存储到mysql数据库
将上传之后的文件从web服务器删除
- 前端html文件解释
- nginx.conf配置(配置完之后记得重启)
- 在浏览器以两种方式输入相应的url,然后观察效果,可以看到,配置完之后,不论是根目录还是二级目录都能访问,效果如下:
在阶段一,我们首先看一下文件上传过程中,会有哪些信息。
- 首先在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存到数据库中,这时候就能实现下载的 *** 作。这就是我们在阶段二要做的事。
第一步:
将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
然后在我们的网址栏,输入这个文件对应的名称,就能看到服务器上所存储的图片了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)