攻克 CRMRB 部署难点:从 PHP 扩展、数据库配置到进程守护

🎯 学习目标

完成本课程后,学习者将能够:

  • 手把手Centos7.9 安装最新版本 CRMRB v5.6.1 单商户应用部署
  • 开放防火墙端口、配置PHP扩展(fileinfo、redis)、禁用函数选项
  • 数据库服务(Mysql、Redis)sql-mode 配置
  • 深入理解Nginx与FastCgi通信方式(Unix Socket 方式 、TCP端口方式)
  • 安装Supervisor ,管理消息队列任务

CRMRB v5.6.1 运行环境要求

这里是摘抄 CRMRB v5.6.1 官网运行环境要求,我使用的是PHP7.4 Mysql 5.7、Redis5.0 、Supervisor 4.3.0,开放防火墙端口即可,这里需要注意的是,如果是Linux环境消息队列的维护是需要再Supervisor管理的。

bash 复制代码
WEB Nginx 
PHP PHP 7.4 
MySQL 5.7(引擎:InnoDB)
缓存 Redis 5.0
管理器 Supervisor 4.3.0
开放端口 80, 21, 8888, 888, 443, 3306, 6379(授权对象:0.0.0.0/0)
PHP 扩展 fileinfo(可选)、redis(可选)
禁用函数 proc_open, pcntl_signal, pcntl_signal_dispatch, pcntl_fork, pcntl_wait, pcntl_alarm
消息队列    运行命令:php think queue:listen --queue (使用Supervisor)
长连接 运行命令:sudo -u www php think workerman start --d (命令行执行)
定时任务    运行命令:php think timer start --d (命令行执行)

一、开放防火墙端口

开放防火墙端口,使网络可服务能够请求,如果是云服务器,设置对应的安全组添加端口,保证网络正常通信是服务的第一步,以80端口为例,CRMRB需要开放80, 21, 8888, 888, 443, 3306, 6379(授权对象:0.0.0.0/0)

bash 复制代码
sudo systemctl start firewalld
sudo systemctl enable firewalld

#添加防火墙开放端口
sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
#重启
sudo firewall-cmd --reload

#查看已经开放的端口
$ sudo firewall-cmd --zone=public --list-ports
2049/tcp 20048/tcp 111/tcp 111/udp 80/tcp 21/tcp 8888/tcp 888/tcp 443/tcp 3306/tcp 6379/tcp

Lnmp 一键安装

我使用的是lnmp.org lnmp2.2 一键安装集成包安装的开发环境,lnmp2.2比较快捷方便适用于小企业进行部署服务、快速验证业务逻辑的过程,安装过程有点慢,需要下载大量的安装包和扩展,需要耐心等待。

环境信息:

Centos7.9 + PHP7.4 + Mysql5.7

PHP 开启扩展 fileinfo(可选)、redis(可选)任意一种,在PHP里配置禁用函数 proc_open, pcntl_signal, pcntl_signal_dispatch, pcntl_fork, pcntl_wait, pcntl_alarm

bash 复制代码
wget https://soft.lnmp.com/lnmp/lnmp2.2.tar.gz -O lnmp2.2.tar.gz 
&& tar zxf lnmp2.2.tar.gz 
&& cd lnmp2.2 
&& ./install.sh lnmp

成功的信息如下

bash 复制代码
============================== Check install ==============================
Checking ...
Nginx: OK
MySQL: OK
PHP: OK
PHP-FPM: OK
Clean Web Server src directory...

1、PHP安装扩展

查看php扩展,是否安装 fileinforedis ,配置禁用函数proc_open, pcntl_signal, pcntl_signal_dispatch, pcntl_fork, pcntl_wait, pcntl_alarm

bash 复制代码
php -m | grep -E "fileinfo|redis"

php.ini 中设置禁用函数,配置disable_functions选项:

bash 复制代码
# php -i | grep php.ini
Configuration File (php.ini) Path => /usr/local/php/etc
Loaded Configuration File => /usr/local/php/etc/php.ini

disable_functions = passthru,exec,system,chroot,chgrp,chown,shell_exec,proc_open,proc_get_status,popen,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,pcntl_signal,pcntl_signal_dispatch,pcntl_fork,pcntl_wait,pcntl_alarm

2、Mysql sql-mode

Mysql 要设置 sql-mode,如果sql_mode,不可以就使用sql-mode,本身应该是已经配置成功了,但是在安装的时候不通过,所以两个都试试。

bash 复制代码
sql_mode = NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

安装时可能遇到的问题

这里有两个可能遇到的问题需要提醒,没有遇到的跳过,一个是关于中科大EPEL失效问题,还有一个就是Nginx与php-fpm通信一致的问题。

1、中科大EPEL失效问题

错误信息http://mirrors.ustc.edu.cn/epel/7/x86_64/repodata/repomd.xml: [Errno 14] HTTP Error 404 - Not Found,从你给出的错误信息可知,CentOS 7.9 在尝试访问中科大(USTC)的 EPEL 镜像源时,找不到 repomd.xml 文件,进而导致 yum 操作失败。

首先,如果之前设置过,更改前记得要备份EPEL 配置文件,这是一个非常良好的习惯。

bash 复制代码
mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup

接着,创建新的 EPEL 配置文件:

bash 复制代码
cat > /etc/yum.repos.d/epel.repo << EOF
[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
baseurl=https://mirrors.aliyun.com/epel/7/$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/epel/RPM-GPG-KEY-EPEL-7
EOF

#刷新缓存
yum clean all
yum makecache

2、Nginx和php-fpm 通信的一致性

Nginx 与 PHP 通信主要有三种方式:FastCGI 模式、CGI 模式和模块模式,但现在都已经采用FastCGI 模式。

FastCGI 模式下主要有两种连接方式:TCP 端口连接Unix Socket 连接。两者都是通过 FastCGI 协议通信,但底层传输方式不同。

  • Unix Socket ,基于文件系统的套接字,本地通信,性能更高(减少网络协议栈开销),但只支持本地传输。
  • TCP 端口连接基于 TCP/IP 协议,通过端口通信,方便灵活,支持(可跨服务器部署)

php-fpm.conf

bash 复制代码
[global]
pid = /usr/local/php/var/run/php-fpm.pid
error_log = /usr/local/php/var/log/php-fpm.log
log_level = notice

[www]
; 监听方式:可以是端口或 
; 端口方式
listen = 127.0.0.1:9000
; Unix Socket 方式
; listen = /tmp/php-cgi.sock;

Redis安装、配置

安装redis服务和扩展、设置配置项(fileinfo、redis扩展 二选一),Redis设置密码、和访问权限。

bash 复制代码
进入lnmp解压后的目录,执行:./addons.sh install redis

ps aux | grep redis
/usr/local/redis/bin/redis-server 0.0.0.0:6379

#全局搜索配置文件
sudo find / -name "redis.conf" 2>/dev/null
/usr/local/redis/etc/redis.conf
bash 复制代码
# 配置绑定ip 0.0.0.0 表示允许任何人访问
bind 0.0.0.0
# 设置密码
requirepass m123456
# 关闭保护模式(允许远程访问)
protected-mode no 

可以手动修改,也可以使用sed修改。

bash 复制代码
sed -i 's/bind 127.0.0.1/bind 0.0.0.0/g' /usr/local/redis/etc/redis.conf
sed -i 's/# requirepass foobared/requirepass m123456/g' /usr/local/redis/etc/redis.conf
sed -i 's/protected-mode no/protected-mode yes/g' /usr/local/redis/etc/redis.conf 

下载V5.6.1源码包

把源码下载到web服务器上,目录结构,需要注意文件权限,配置Nginx,web服务器root参数是 /home/wwwroot/work/crmeb/public

bash 复制代码
[stark@bogon work]$ tree -L 1
.
├── crmeb
├── docker-compose
├── LICENSE
├── readme
├── README.md
└── template

Nginx 部署 web站点

Nginx配置,这里有一个伪静态和长连接,不要漏掉,长连接端口和官方保持一致,伪静态的配置一定要保持一致,不然请求会出错,要注意Nginx 和 PHP的所属用户和用户组权限。

bash 复制代码
# 使用tee命令将Nginx配置文件写入CentOS 7.9系统
sudo cat << 'EOF' | sudo tee /usr/local/nginx/conf/vhost/work.conf > /dev/null
server {
    listen       80;
    server_name  www.work.com;
    root        /home/wwwroot/work/crmeb/public;

    location / {
        index  index.php index.html;
        if (!-e $request_filename) {
            rewrite  ^(.*)$  /index.php?s=$1  last;
            break;
        }
        autoindex  off;
    }
    
    location ~ .php(.*)$ {
        #fastcgi_pass  127.0.0.1:9000; #TCP端口方式
        fastcgi_pass unix:/tmp/php-cgi.sock; #Unix Socket 方式
        fastcgi_index index.php; #默认索引文件
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name; #设置 PHP 脚本的绝对路径(关键参数)
        include  fastcgi_params;
    }

    location /notice {
        proxy_pass              http://127.0.0.1:40001/;
        proxy_http_version      1.1;
        proxy_set_header        Upgrade $http_upgrade;
        proxy_set_header        Connection "upgrade";
        proxy_set_header        X-real-ip $remote_addr;
        proxy_set_header        X-Forwarded-For $remote_addr;
    }

    location /msg {
        proxy_pass              http://127.0.0.1:40002/;
        proxy_http_version      1.1;
        proxy_set_header        Upgrade $http_upgrade;
        proxy_set_header        Connection "upgrade";
        proxy_set_header        X-real-ip $remote_addr;
        proxy_set_header        X-Forwarded-For $remote_addr;
    }
}
EOF

长连接、定时任务、消息队列

在php.ini中 配置之前请先删除以下php的禁用函数,配置项disable_functions,也就是disable_functions不包含他们。

bash 复制代码
proc_open
pcntl_signal
pcntl_signal_dispatch
pcntl_fork
pcntl_wait
pcntl_alarm

1、设置客服长连接 启动workerman服务

启动sudo -u www php think workerman start --d ,下面的页面就是启动成功了。

bash 复制代码
[stark@bogon crmeb]$ sudo -u www php think workerman start --d
string(5) "admin"
string(4) "chat"
string(7) "channel"
Workerman[think] start in DAEMON mode
-------------------------------------------- WORKERMAN ---------------------------------------------
Workerman version:3.5.19          PHP version:7.4.33
--------------------------------------------- WORKERS ----------------------------------------------
proto   user            worker           listen                       processes    status
tcp     www             none             websocket://0.0.0.0:40001    1             [OK]
tcp     www             none             websocket://0.0.0.0:40002    1             [OK]
tcp     www             ChannelServer    frame://127.0.0.1:40003      1             [OK]
----------------------------------------------------------------------------------------------------
Input "php think stop" to stop. Start success.

2、启用定时任务

启动定时任务php think timer start --d,得到下面的页面就是启动成功了。

bash 复制代码
[stark@bogon crmeb]$ php think timer start --d
Workerman[think] start in DAEMON mode
------------------------------------- WORKERMAN --------------------------------------
Workerman version:3.5.19          PHP version:7.4.33
-------------------------------------- WORKERS ---------------------------------------
proto   user            worker          listen          processes    status
tcp     stark           none            none            1             [OK]
--------------------------------------------------------------------------------------
Input "php think stop" to stop. Start success.

3、启用消息队列

消息队列需要先安装Supervisor 来进行管理队列已经安装Supervisor的可跳过安装过程,Supervisor 是 Python 编写的工具,首先需要确保系统有 Python 和 pip:

bash 复制代码
# 检查Python版本(CentOS 7通常预装Python 2.7)
python -V

# 安装pip(Python包管理工具)
yum install -y epel-release
yum install -y python-pip

# 升级pip到最新版本
pip install --upgrade pip

sudo pip install supervisor

生成 Supervisor 配置文件,添加配置

bash 复制代码
sudo mkdir -p /etc/supervisor/conf.d
sudo echo_supervisord_conf > /etc/supervisor/supervisord.conf

vim /etc/supervisor/supervisord.conf

[include]
files = /etc/supervisor/conf.d/*.conf

下面是配置详解:

bash 复制代码
[unix_http_server]
file=/tmp/supervisor.sock   ; UNIX socket 文件

[inet_http_server]         ; 启用HTTP服务器,便于通过网页管理
port=0.0.0.0:9001          ; 监听所有IP的9001端口
username=user              ; 用户名(可选)
password=123               ; 密码(可选)

[supervisord]
logfile=/var/log/supervisord.log ; 日志文件
logfile_maxbytes=50MB        ; 日志大小限制
logfile_backups=10           ; 日志备份数量
loglevel=info                ; 日志级别
pidfile=/var/run/supervisord.pid ; PID文件
nodaemon=false               ; 是否以守护进程运行
minfds=1024                  ; 最小文件描述符
minprocs=200                 ; 最小进程数

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; 与supervisord通信的socket

创建 Supervisor 系统服务,vim /usr/lib/systemd/system/supervisord.service

bash 复制代码
[Unit]
Description=Supervisor daemon
After=network.target

[Service]
Type=forking
ExecStart=/usr/bin/supervisord -c /etc/supervisor/supervisord.conf
ExecStop=/usr/bin/supervisorctl shutdown
ExecReload=/usr/bin/supervisorctl reload
User=root
Restart=on-failure

[Install]
WantedBy=multi-user.target
bash 复制代码
# 重新加载systemd配置
systemctl daemon-reload

# 启动Supervisor
systemctl start supervisord

# 设置开机自启
systemctl enable supervisord

# 检查运行状态
systemctl status supervisord

验证安装

bash 复制代码
# 查看Supervisor版本
supervisord -v

在 Supervisor 的配置目录下创建一个专门的配置文件,创建CRMRB消息队列任务:

bash 复制代码
sudo vim /etc/supervisor/conf.d/think-queue.conf

将以下内容添加到文件中(根据你的实际情况修改路径):

bash 复制代码
[program:think-queue]
; 命令路径,需替换为你的项目实际路径
command=/usr/bin/php /home/wwwroot/work/crmeb/think queue:listen --queue

; 项目根目录,需替换为你的项目实际路径
directory=/home/wwwroot/work/crmeb/public

; 运行队列的用户(根据你的 Web 服务器用户设置)
user=www

; 自动启动
autostart=true

; 程序意外退出时自动重启
autorestart=true

; 启动重试次数
startretries=3

; 日志输出配置
redirect_stderr=true
stdout_logfile=/var/log/think-queue.log

; 日志文件大小限制
stdout_logfile_maxbytes=10MB

; 日志文件备份数量
stdout_logfile_backups=10

; 进程启动超时时间
startsecs=5

; 停止信号
stopsignal=INT

应用配置并重新启动:

bash 复制代码
# 重新读取配置文件
sudo supervisorctl reread

# 更新配置
sudo supervisorctl update

# 启动队列进程
sudo supervisorctl start think-queue

# 查看进程状态
sudo supervisorctl status think-queue

看见这个的时候,就是已经配置成功了,去后台自己开启一下就行了。

bash 复制代码
[root@bogon crmeb]# sudo supervisorctl status
think-queue                      RUNNING   pid 32811, uptime 0:00:45

需要注意的安全机制

bash 复制代码
location ~ .php(.*)$ {
    fastcgi_pass unix:/tmp/php-cgi.sock; #Unix Socket 方式
    fastcgi_index index.php; #默认索引文件
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name; #设置 PHP 脚本的绝对路径(关键参数)
    fastcgi_split_path_info  ^((?U).+.php)(/?.+)$; #用于分割 URL 中 PHP 脚本路径和额外的路径信息(PATH_INFO)
    fastcgi_param  PATH_INFO  $fastcgi_path_info; #传递 PATH_INFO(额外路径信息)给 PHP
    fastcgi_param  PATH_TRANSLATED  $document_root$fastcgi_path_info; #设置 PATH_INFO 对应的文件系统路径
    include fastcgi_params;
}

PATH_TRANSLATED 的安全风险,这一行会将用户请求的路径信息直接映射到文件系统路径,可能被恶意用户利用来访问系统上的任意文件。

现代 Nginx 和 PHP-FPM 默认配置了安全限制,防止路径遍历攻击:

  • open_basedir 限制
  • doc_root 限制
  • Nginx 的安全模块检测

这个配置导致 "Access denied" 错误的主要原因是 安全限制 。php开启这个就会产生错误信息Access denied.通常来说,大多数现代 PHP 应用不需要 PATH_TRANSLATED 参数,移除它即可解决问题。

前端/调试

环境版本node v20.19.2,npm 11.6.2,npm 在低依赖包有报错信息,安装依赖就可以看见欢迎页面了,uni-app使用HBuilder X的启动,服务就可以正常运行了,万里长征第一步就这样完成了。

bash 复制代码
npm install 
npm run dev

😄 Hello ~ 欢迎使用CRMEB标准版,我们将竭诚为您服务!
info - [提示] 点击这里查看更多商品~ https://doc.crmeb.com
info - [提示] 点击这里可以查看开发文档喔~ https://www.crmeb.com
info - [提示] 点击这里可以查看我们的论坛社区~ https://www.crmeb.com/ask
info - [你知道吗?] 按 Ctrl+C 可以停止服务呢~
相关推荐
罗政4 小时前
【免费】轻量级服务器centos监控程序+内存+cpu+nginx+适合小型站长使用
服务器·nginx·centos
爬山算法4 小时前
Redis(60) Redis的复制延迟如何优化?
redis·bootstrap·php
JaguarJack9 小时前
PHP "真异步" TrueAsync SAPI 与 NGINX Unit 集成
后端·php
晓风残月淡12 小时前
JVM字节码与类的加载(二):类加载器
jvm·python·php
椎49517 小时前
苍穹外卖前端nginx错误之一解决
运维·前端·nginx
Wx-bishekaifayuan21 小时前
基于微信小程序的社区图书共享平台设计与实现 计算机毕业设计源码44991
javascript·vue.js·windows·mysql·pycharm·tomcat·php
noravinsc21 小时前
centos如何做的时间同步
linux·运维·centos
2301_787328491 天前
25.负载均衡-Nginx、HAProxy、LVS 全解析
nginx·负载均衡·lvs
siriuuus1 天前
Nginx 负载均衡调度算法
运维·nginx·负载均衡