windows下部署nginx、php、mysql
Nginx
1. 下载与安装
nginx比较简单直接,到官网下载一个面向window的zip压缩包,解压到自己想安装的地方即可。
本文以 nginx版本1.23.3,根目录 D:\software\nginx-1.23.3 为例。
2. 配置
(1) 需要修改的nginx配置文件是:D:\software\nginx-1.23.3\conf\nginx.conf
由于nginx.conf如何配置与实际项目密不可分,所以此处不做配置展示
一般情况下,知名的Web应用项目团队都会提供一段官方建议的nginx.conf配置,帮助用户实现部署
(2) 设置环境变量
在系统变量Path中,添加nginx根目录
查看nginx版本(用于检查环境变量是否配好)nginx -v
3. 启动与停止命令
(1) 启动:直接运行nginx.exe(一闪而过,创建2个进程) 或 使用命令(需配置环境变量)start nginx
(2) 只启动一个nginx时,可使用该命令停止nginx -s quit
(完整有序的停止nginx)nginx -s stop
(快速停止nginx)
(3) 启动了多个nginx时,使用该命令停止所有nginx进程taskkill /f /t /im nginx.exe
启动多个nginx时,无法通过多次执行 nginx -s quit 来停止全部进程
重载配置:nginx -s reload
PHP
1. 下载与安装
到官网下载与系统对应的php即可,对于面向windows的php安装包,官方提供线程安全/非线程安全两种版本。对于使用nginx的情景,需要选非线程安全的安装包。下载后解压到指定的目录即可。
本文以 php-8.1.29-nts-Win32-vs16-x64 为例(https://windows.php.net/downloads/releases/php-8.1.29-nts-Win32-vs16-x64.zip)
php根目录为 D:\software\php-8.1.29-nts-Win32-vs16-x64
2. 配置php.ini
(1) 建立php.ini
php的配置文件是php.ini,但安装包内并不自带该文件。php官方提供php.ini-development和php.ini-production两个预配置文件。个人根据使用情景,选择一个复制并重命名为php.ini。
开发环境下,一般选php.ini-development复制并重命名为php.ini。
(详见文件内的“About this file”段落)
(2) 在php.ini中,开启php官方预置的扩展(去掉开头分号以取消注释),下面这些是一般要打开的
extension=curl
extension=fileinfo
extension=gd
extension=gmp
extension=mbstring
extension=mysqli
extension=openssl
extension=pdo_mysql
extension=openssl
extension=sodium
(3) 可选: 其它可能需要修改的默认配置
可能需要将php脚本的内存限制调大,否则某些项目启动将会提示内存不足memory_limit = 128M
post_max_size = 50M
upload_max_filesize = 50M
max_execution_time = 300
可能需要将此项取消注释,才能正确加载官方预制扩展的路径extension_dir = "ext"
安全设置 cgi.fix_pathinfo = 0
、fastcgi.impersonate = 1
、cgi.force_redirect = 0
、expose_php = Off
往都是设置cgi.fix_pathinfo = 1,但现在发现有重大漏洞,原因举例:
3. 环境变量
(1) 在系统环境变量Path中加入php根目录路径 D:\software\php-8.1.29-nts-Win32-vs16-x64
(2) 打开命令行,用 php -v 或 php -i 检验
就一个程序本身而言,大多数时候,环境变量不是必须添加的。添加环境变量的主要原因有两个:(1)某些情景下,一个程序会通过系统变量寻找它需要/依赖/关联的另一个程序或参数值;(2)为了让一个程序能方便地在任意工作目录下调用。
当访问www.xx.com/phpinfo.jpg/1.php这个URL时,$fastcgi_script_name会被设置“phpinfo.jpg/1.php”,然后构造成SCRIPT_FILENAME(绝对路径)传递给PHP CGI,如果开启了cgi.fix_pathinfo=1选项(这个默认值就是1,所以没有设置过就是开启),那么就会触发在PHP中的如下逻辑:
PHP会认为SCRIPT_FILENAME(绝对路径)是phpinfo.jpg,而1.php是PATH_INFO,所以就会phpinfo.jpg作为PHP文件来解析了.
也是一个逻辑问题,所以说我们只需要在正常的.jpg后面加/.php就可以成功的绕过解析
如果某些网站打开后提示No input file specified.
,那只能使用 cgi.fix_pathinfo = 1
,值不能为0。
Nginx + PHP CGI的一个可能的安全漏洞(2010年)
https://www.laruence.com/2010/05/20/1495.html
http://域名/项目名/入口文件/模块名/方法名/键1/值1/键2/值2属于URL访问模式中的PATHINFO 模式,很多框架采用的URL访问模式就是这种,例如ThinkPHP。这种访问模式必须开启cgi.fix_pathinfo,同时php配置的默认情况也是cgi.fix_pathinfo=1。
4. 安装扩展
(1)安装redis扩展
下载地址:https://windows.php.net/downloads/pecl/releases/
找到对应的扩展下载,需确保与php匹配
redis:https://windows.php.net/downloads/pecl/releases/redis/5.3.7/php_redis-5.3.7-8.1-nts-vs16-x64.zip
igbinary:https://windows.php.net/downloads/pecl/releases/igbinary/3.2.7/php_igbinary-3.2.7-8.1-nts-vs16-x64.zip
下载后将php_redis.dll/pdb、php_igbinary.dll/pdb拷贝到ext目录。
修改php.ini添加:
extension=php_igbinary.dll
extension=php_redis.dll
重启服务,通过php -m
查看扩展是否安装成功
Mysql
1. 下载与安装
使用官方提供的下载地址:https://dev.mysql.com/downloads/mysql/
免安装版只需要选择一个合适的路径解压即可,下文将以解压到路径 D:\software\ALLmysql 为例。
解压后,mysql根目录为 D:\software\ALLmysql\mysql-8.0.30-winx64
2. 写初始配置
(1) 在mysql根目录下创建my.ini文件,写入如下内容后保存。
[client]
# 设置mysql客户端连接服务端时默认使用的端口
port=3306
default-character-set=utf8mb4
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8mb4
[mysqld]
#设置3306端口
port = 3306
# 设置mysql的安装目录
basedir=D:\\software\\ALLmysql\\mysql-8.0.30-winx64
# 设置mysql数据库的数据的存放目录
datadir=D:\\software\\ALLmysql\\mysql-8.0.30-winx64\\sql_data
# 允许最大连接数
max_connections=200
# 允许连接失败的次数。这是为了防止有人从该主机试图攻击数据库系统
max_connect_errors=20
# 服务端使用的字符集默认为utf8mb4字符集
character-set-server=utf8mb4
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB
# 忽略密码
# skip-grant-tables
此配置内容来自搜索拼凑,需根据实际调整。如果只是本地运行的话,某些设置用不上。
mysql配置文件的官方文档: https://docs.oracle.com/cd/E17952_01/mysql-8.0-en/option-files.html
zip安装包不提供my.ini文件。若在Windows下使用安装器安装,完成后将在根目录下生成my.ini文件。
(2) 创建一个mysql数据的存放目录
mysql要根据my.ini做初始化,但初始化时可能无法正确创建my.ini中配置的数据存储目录。
因此,如果my.ini中配置的数据存储路径不存在,要先手动创建。
如果路径不存在,初始化时可能报错,也可能自动创建一个与根目录并列的文件夹用于储存。
(3) 配置系统环境变量
只需要把mysql根目录下的bin文件夹加到系统环境变量即可,推荐做法:
添加系统变量,变量名: MYSQL_HOME 路径: mysql根目录
编辑系统变量Path,加入一条路径: %MYSQL_HOME%\bin
这样做的优点是:如果mysql根目录改变,或者需要在多个mysql间切换,在改环境变量时,只需要修改MYSQL_HOME的路径即可。
3. 初始化mysql及注册服务
(1) 管理员模式运行cmd或powershell,进入mysql根目录下bin文件夹
# 若使用CMD,则cd命令要加/d参数,否则无法跨磁盘分区切换工作目录
cd D:\software\ALLmysql\mysql-8.0.30-winx64\bin
(2) 初始化mysql
# 根据my.ini初始化
# --console: 将错误日志打印到控制台,否则错误日志将写入日志文件中
.\mysqld --initialize --console
mysql有默认的root用户,初始化时生成root用户的随机密码并输出在控制台,记住这串root密码
(3) 将当前这个mysql加入为系统的服务项
mysqld -install
(4) 用命令启动mysql服务
net start mysql
停止mysql服务net stop mysql
注册为系统服务后,也可以在 任务管理器→服务 中控制mysql服务的启动/停止
(5) mysql登录与基本初始操作
# 登录本机3306端口上运行的mysql-server, 用户为root
# -p参数是密码,留空表示交互式输入,root初始密码是之前mysql初始化时生成的
mysql -h 127.0.0.1 -P 3306 -u root -p
# 将root用户密码改为自设的密码,这里以123456为例
alter user root@localhost identified by '123456';
# 新建一个名为test1的数据库
create database test1;
# 新建一个名为test2的数据库并指定默认字符集为utf8mb4
create database test2 character set utf8mb4 collate utf8mb4_unicode_ci;
# 创建用户名alice,密码123456,允许通过 ip=localhost 登录
create user alice@localhost identified by '123456';
# 创建用户名guest,密码123456,允许通过 ip=任意 登录
create user guest@% identified by '123456';
# 授予 用户alice@localhost 操作 数据库test1(的所有表)的全部权限
# grant all 与 grant all privileges 没有区别
grant all on test1.* to alice@localhost;
# 查看用户alice@localhost被授予的权限
show grants for 'alice'@'localhost';
# 删除用户guest@%
drop user guest@%;
# 删除数据库test2
drop database test2;
# 退出登录
exit;
退出登录不会让服务停止运行
对于创建用户,你可能在网上看到形如 'name'@'localhost' 的加单引号写法,这在mysql8.0中是没有必要的
附1. 卸载方法
以上述方式安装的mysql,这样卸载后就不会影响重装了:
(1) 管理员模式运行cmd,将mysql从系统服务项中删除sc delete mysql
(2) 删除mysql根目录文件夹
视情况附加:删除mysql的数据储存文件夹、删除/清空/更改之前配置的MYSQL_HOME环境变量
附2. 以非服务方式启动(多个)mysql-server
windows下似乎只能将一个mysql设为环境变量&系统服务。如果要同时启动多个mysql,分别在每个mysql根目录下cmd启动mysql即可。
假设win10系统中启动了mysql8.0后,又要启动mysql5.7,那么操作如下:
(1) 修改mysql5.7的my.ini中的端口配置,保证与其它正在运行的mysql无端口冲突
(2) 进入mysql5.7根目录下的bin目录,打开命令行
# 这种启动方式需要给出my.ini的路径
# 本文以my.ini位于mysql的根目录下为例
./mysqld.exe --defaults-file=..\my.ini
(3) 关闭命令行窗口,mysql5.7即停止运行
Nginx,PHP,Mysql联动
1. 启动php-cgi
在php的根目录下,打开命令行窗口,用如下命令启动php-cgi
如果php.ini不在php根目录下,则需明确php.ini的路径php-cgi -b 127.0.0.1:9000 -c php.ini
关闭命令行窗口,则php-cgi停止
windows下没有php-fpm,而单独的php-cgi进程有时会因为一些原因自动停止。如果遇到该问题,可以使用xxfpm(一个window平台下的一个php-cgi进程管理工具)自动新建php-cgi进程并维护数量。
对于该问题,可以参见:十年了,xxfpm 终于更新了
如果想隐藏启动后的php-cgi命令行窗口,可以使用RunHiddenConsole
2. 配置并启动nginx
(1) 设置与php-cgi的联动:以http://localhost:80为例,将相应server段简单改成如下状态
server {
# 监听以server_name=localhost发送到本地80端口的请求
# 如果给项目配过本地域名,server_name可以设相应本地域名
listen 80;
server_name localhost;
# window下的nginx安装包自带一个html文件夹,作为网站根目录
# 如果有自己的项目,可以设为自己的网站根目录
root D:\software\nginx-1.23.3\html
# 如果传入url没有指定到文件,则依次尝试寻找index设置的文件
index index.php index.html site.php site.html;
# 将错误码为50x的错误页面重定向到 根目录/html/50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# 当收到php文件的请求时,转发给php-cgi处理
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
fastcgi_pass 的 ip:端口 与php-cgi运行配置的 ip:端口 保持一致
fastcgi_split_path_info 及其下面一行实现的是“在nginx处理阶段,用正则表达式提取url,填充PATH_INFO变量”,此处涉及一个古早的服务器端php漏洞——cgi.fix_pathinfo漏洞。不过在本地开发时,不加这两行也无所谓。
(2) 在nginx的网站根目录中新建一个index.php文件,内容如下:
<?php
phpinfo();
?>
(3) 启动nginx,启动方式参见本文第一部分
(4) 打开浏览器,url输入localhost,在php-cgi、nginx启动且二者配置正确的情况下,此时应看到phpinfo页面
3. 启动mysql
注册了服务的mysql,可以用如下命令控制启动/停止,也可以在 「任务管理器」→「服务」中控制启动/停止
启动mysql服务net start mysql
停止mysql服务net stop mysql
未注册服务的mysql,可以用命令行控制mysql启动/停止
具体参见上文“附2. 以非服务方式启动(多个)mysql”
启动后,让需要mysql的项目连接到该mysql配置的端口即可
start_php_cgi.bat
@echo off
REM 每个进程处理的最大请求数,或设置为 Windows 环境变量
set PHP_FCGI_MAX_REQUESTS=1000
echo Starting PHP FastCGI...
RunHiddenConsole D:/sensen/xxfpm/bin/xxfpm.exe "D:/php-8.1.29/php-cgi.exe -c D:/php-8.1.29/php.ini" -n 5 -i 127.0.0.1 -p 9000
PAUSE