攻克 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 可以停止服务呢~
相关推荐
Avan_菜菜9 天前
FRP 内网穿透完整实战:从 HTTP 映射到 HTTPS 自签代理
运维·nginx·https
两个人的幸福11 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
ping某13 天前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx
BingoGo13 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack13 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户30745969820714 天前
PHP 扩展——从入门到理解
php
鹏仔先生15 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下15 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
xingpanvip15 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
2601_9618752415 天前
决战申论100题2026|最新|范文
linux·容器·centos·debian·ssh·fabric·vagrant