一个客户部署在阿里云服务器上的2个网站因欠费被关停,客户的软件开发方2016年8月做过一次网站数据库备份,对网站目录做了一次打包备份,两个网站数据接近30G,网站基于PHP-MYSQL开发,采用国内比较流行的ThinkPHP架构,原站部署采用WAMP(WIN2008+APACHE+MYSQL+PHP)方式,由于客户没有购买软件方维保服务,所以客户软件方没有提供任何有价值的部署文档,只提供网站备份打包文件及数据库导出sql文件。客户要求将网站数据恢复部署到电信天翼云中。下面将数据恢复过程中遇到的坑梳理回顾一遍。
一、数据恢复主要流程
1、通过ansible自动在云主机部署LNMP环境
ansible主机目录结构如上图:创建hosts文件,lnmp.yml文件、vars目录,及vars目录中的main.yml文件
hosts文件内容如下:
[lnmp]
10.37.6.6
lnmp.yml文件如下:
---
- hosts: lnmp
become: yes
vars_files:
- vars/main.yml
roles:
- { role: geerlingguy.mysql }
- { role: geerlingguy.nginx }
- { role: geerlingguy.php }
vars/main.yml文件内容如下:
mysql_root_password: xxxxxx
mysql_databases:
- name: example_db #你准备创建的数据库名称
encoding: utf8
collation: utf8_general_ci
mysql_users:
- name: bklyj #你准备在数据库中初始化创建的用户名
host: "%"
password: xxxxxx #对应bklyj用户的数据库登陆密码
priv: "example_db.*:ALL" #对应bklyj用户的可访问数据库及权限
php_memory_limit: "128M"
php_max_execution_time: "90"
php_upload_max_filesize: "256M"
php_packages:
- php
- php-cli
- php-common
- php-devel
- php-gd
- php-mbstring
- php-pdo
- php-pecl-apcu
- php-xml
- php-fpm
以上过程需要您熟悉ansible自动部署脚本及原理并搭建好ansible运行环境 ,最后通过一条命令即可完成对目标云主机LNMP运行环境的自动化部署。
ansible-playbook -i hosts lnmp.yml
整个部署过程大约需要5分钟时间,如果您不会使用ansible,可以手工在云主机上分别安装如下软件即可:
MySQL---或 Mariadb、Nginx、php、php-fpm、php-cli、php-common、php-devel、php-gd、php-mbstring、php-pdo、php-pecl-apcu、php-xml
nginx无法直接使用php,必须配合fastcgi接口实现对php的调用,而php-fpm就是实现这一接口的进程,所以当需要处理php请求时,nginx的worker进程会将请求移交给php-fpm的worker进程进行处理,看起来是nginx调用了php,严格讲是nginx间接调用php。
2、云主机配置php-fpm,及php配置文件php.ini
vi /etc/php-fpm.d/www.conf
修改内容如下,将下面内容在www.conf中的部分前面的;去掉
user = nginx
group = nginx
security.limit_extensions = .php .php3 .php4 .php5
修改完成后执行
systemctl enable php-fpm
systemctl start php-fpm
下面修改云主机上php的配置文件/etc/php.ini,完成对php运行环境配置
date.timezone = PRC
short_open_tag = ON
pdo_mysql.default_socket=/var/lib/mysql/mysql.sock
cgi.fix_pathinfo=1
session.save_path = "/var/www" #如果不配置会出现session异常,验证码一直错误,无法登陆故障
3、云主机配置nginx确保ThinkPHP
在/etc/nginx/conf.d/目录下新建客户网站配置文件如下,名字好记就行,关键是文件后缀一定是.conf,内容必须要符合nginx规范
vi /etc/nginx/conf.d/bkly.conf
server {
listen 8000; #网站监听端口
server_name localhost; #网站域名或主机名
root /var/www/bkly; #网站文件根目录
index index.html index.htm index.php;
rewrite_log on;
error_page 404 /404.html;
location = /404.html {
return 404 'Sorry, File not Found!';
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html; # windows用户替换这个目录
}
location / {
try_files $uri @rewrite;
}
location @rewrite {
set $static 0;
if ($uri ~ \.(css|js|jpg|jpeg|html|htm|png|gif|ico|woff|eot|svg|css\.map|min\.map)$) {
set $static 1;
}
if ($static = 0) {
rewrite ^/(.*)$ /index.php?s=/$1;
}
}
location ~ /Uploads/.*\.php$ {
deny all;
}
location ~ \.php/ {
if ($request_uri ~ ^(.+\.php)(/.+?)($|\?)) { }
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param SCRIPT_NAME $1;
fastcgi_param PATH_INFO $2;
fastcgi_param SCRIPT_FILENAME $document_root$1;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
4、拷贝备份网站数据库、 备份网站压缩包到云主机
将备份数据文件放入云主机,通过sftp方式或者在云主机上安装lrzsz工具,通过rz命令接收备份文件
-rw-r--r-- 1 nginx nginx 10278442 Apr 26 07:51 bkly.sql
-rw-r--r-- 1 root root 14441590853 Jul 12 15:45 bkly.zip
网站数据包恢复:unzip bkly.zip -d /var/www/bkly
将网站压缩包直接恢复到/var/www/bkly目录下
5、云主机数据库创建用户目标数据库并恢复网站数据库数据
通过下面的命令将网站备份数据直接导入网站数据库example_db中
mysql -u bklyj -pxxxxxx example_db < /var/www/bkly.sql
6、设置linux内置防火墙网络端口,放开网站对应端口,并通过浏览器验证网站访问是否正常
firewall-cmd --permanent --add-port=8000/tcp && firewall-cmd --permanent --add-port=80/tcp && firewall-cmd --reload
网站监听通过8000端口,所以需要通过web浏览器访问网站对应IP的8000端口,如果是天翼云主机,对外监听端口应改为80,并且需要提前进行网站备案方便打开端口
http://x.x.x.x 具体效果如下
二、存在的问题
1、网站伪静态页面在nginx下无法使用,必须切换到apache下
由于恢复的两个网站分别采用了不同的策略进行访问,一个网站使用上面的配置完全正常,但是另一个网站通过apache加载rewrite模块通过.htaccess文件定义了大量伪静态页面,这些页面在nginx下无法正常访问,显示错误信息无法加载控制器,通过观察nginx的error日志及分析源码发现这些伪静态页面的加载实际是需要通过apache的rewrite模块做了网页内重定向在url浏览器地址栏中显示的是html静态页面实际上是通过动态加载实现的页面。
Nginx一是不支持.htaccess;二是不支持404页伪静态。这2项,Apache都完美支持。
这个问题困扰了我1天时间,一开始没有理解thinkphp实现所谓伪静态页面的原理,把排除故障重点放在数据是否完整,网站缓存数据是否存在问题方面,在最终确定是伪静态页面转换出问题后,又把重点放在如何利用nginx的rewrite功能实现类似apache的.htaccess功能,不停的修改nginx配置文件,通过拦截url关键词实现类似的伪静态功能,但是这样尝试除了浪费时间没有真正解决问题,最后是通过彻底停用nginx,将应用切换为apache实现。
a、apache配置脚本需新增2个网站的配置文件
在/etc/httpd/conf.d目录下新增网站配置文件如下所示,两个网站分别使用80与8000端口承载,具体内容如下:
[root@localhost conf.d]# cat bkly.conf
<VirtualHost *:80>
ServerAdmin admin@localhost
ServerName localhost:80
DocumentRoot "/var/www/bkly"
<Directory "/var/www/bkly">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:8000>
ServerAdmin admin@localhost
ServerName localhost:8000
DocumentRoot "/var/www/bkzx"
<Directory "/var/www/bkzx">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
主要配置项目解释说明
- ServerSignature On => ServerSignature Off // 配置错误页不显示Apache版本 --httpd.conf
- Options Indexes FollowSymLinks => Options FollowSymLinks // 配置Apache不能通过目录层级进行文件访问
- AllowOverride None => AllowOverride All // 配置允许.htaccess
- DirectoryIndex index.html => DirectoryIndex index.html index.php // 配置Apache支持.php文件解析 --httpd.conf
b、apache主配置文件修改
vi /etc/httpd/conf/httpd.conf
Listen 80 #网站1监听端口,与上面的网站1配置端口一致
Listen 8000 #网站2监听端口,与上面的网站2配置端口一致
#DocumentRoot "/var/www/bkly" 注释掉行
2、网站目录及文件属组及群组与容器不一致导致网站打开异常
原则:采用nginx容器时,/var/www/xxx网站目录的owner、group必须都是nginx,如果采用apache容器时,则对应的网站目录的owner、group必须为apache,并且网站目录下的权限为755
网站一首页显示:
网站二首页显示:
3、备份数据不全导致部分网页无法恢复
在新闻咨询中有2018年的大量咨询信息,这些信息由于网站数据库备份文件生成于2016年8月,但是网站备份数据是2018年最新数据,由于首页是生成好的静态页面只保存了标题信息,真正的内容信息必须要数据库中存在才能显示,这部分信息只有数据库数据完整才能恢复,否则无法恢复。
总结:
客户的两个网站虽然都采用了同一个开源框架实现,但是网站架构及具体实现细节差别非常大,比如网站一就没有使用伪静态页面技术,用LNMP可以非常完美的解决网站一的数据恢复问题,但同样的配置用到网站二就无法正常使用,必须切换到apache下才能完整的恢复网站二功能,最后经过权衡决定将两个网站都用apache配置打开,通过监听不同的端口实现。Rewirte主要的功能就是实现URL的跳转,隐藏URL真实地址,可以帮组我们实现拟静态,拟目录,域名跳转,防止盗链,搜索引擎得收录等。Rewirte配置可以通过服务器级的(httpd.conf)和目录级的 (.htaccess)两种方式实现