攻克 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管理的。
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)
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
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
成功的信息如下
============================== Check install ============================== Checking ... Nginx: OK MySQL: OK PHP: OK PHP-FPM: OK Clean Web Server src directory...
1、PHP安装扩展
查看php扩展,是否安装 fileinfo,redis ,配置禁用函数proc_open, pcntl_signal, pcntl_signal_dispatch, pcntl_fork, pcntl_wait, pcntl_alarm
php -m | grep -E "fileinfo|redis"
php.ini 中设置禁用函数,配置disable_functions选项:
# 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,本身应该是已经配置成功了,但是在安装的时候不通过,所以两个都试试。
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 配置文件,这是一个非常良好的习惯。
mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup
接着,创建新的 EPEL 配置文件:
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
[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设置密码、和访问权限。
进入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
# 配置绑定ip 0.0.0.0 表示允许任何人访问 bind 0.0.0.0 # 设置密码 requirepass m123456 # 关闭保护模式(允许远程访问) protected-mode no
可以手动修改,也可以使用sed修改。
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。
[stark@bogon work]$ tree -L 1 . ├── crmeb ├── docker-compose ├── LICENSE ├── readme ├── README.md └── template
Nginx 部署 web站点
Nginx配置,这里有一个伪静态和长连接,不要漏掉,长连接端口和官方保持一致,伪静态的配置一定要保持一致,不然请求会出错,要注意Nginx 和 PHP的所属用户和用户组权限。
# 使用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不包含他们。
proc_open pcntl_signal pcntl_signal_dispatch pcntl_fork pcntl_wait pcntl_alarm
1、设置客服长连接 启动workerman服务
启动sudo -u www php think workerman start --d ,下面的页面就是启动成功了。
[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,得到下面的页面就是启动成功了。
[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:
# 检查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 配置文件,添加配置
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
下面是配置详解:
[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
[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
# 重新加载systemd配置 systemctl daemon-reload # 启动Supervisor systemctl start supervisord # 设置开机自启 systemctl enable supervisord # 检查运行状态 systemctl status supervisord
验证安装
# 查看Supervisor版本 supervisord -v
在 Supervisor 的配置目录下创建一个专门的配置文件,创建CRMRB消息队列任务:
sudo vim /etc/supervisor/conf.d/think-queue.conf
将以下内容添加到文件中(根据你的实际情况修改路径):
[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
应用配置并重新启动:
# 重新读取配置文件 sudo supervisorctl reread # 更新配置 sudo supervisorctl update # 启动队列进程 sudo supervisorctl start think-queue # 查看进程状态 sudo supervisorctl status think-queue
看见这个的时候,就是已经配置成功了,去后台自己开启一下就行了。
[root@bogon crmeb]# sudo supervisorctl status think-queue RUNNING pid 32811, uptime 0:00:45
需要注意的安全机制
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的启动,服务就可以正常运行了,万里长征第一步就这样完成了。
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 可以停止服务呢~
更多推荐


所有评论(0)