1. 项目概述:为什么在 Ubuntu 20.04 上部署 ERPNext 不是“装个软件”那么简单
ERPNext 是一个真正能跑通采购、销售、库存、财务、HR、制造全链条的开源企业资源计划系统,不是 WordPress 插件那种点几下就能用的玩具。我从 2018 年开始在生产环境里用它管过三家公司——一家做工业配件分销,一家做定制化家具,还有一家是跨境小批量代工。每次重装 ERPNext,我都得重新翻一遍日志、重调一次 MariaDB 的 buffer pool、再确认一遍 Node.js 版本和 npm 包锁死策略。这不是矫情,而是因为 ERPNext 的技术栈本身就是一个“精密咬合的齿轮组”:Python(后端逻辑)、MariaDB(事务核心)、Node.js(前端构建与实时通信)、Redis(队列与缓存)、Nginx(反向代理)、Supervisor(进程守护)——少一个齿,整台机器就打滑。
你搜到的“Ubuntu 20.04 安装 ERPNext”教程,90% 停留在
curl -s https://raw.githubusercontent.com/frappe/bench/master/install_scripts/setup_frappe.sh | bash
这一行命令上。但现实是:这条命令在你本地跑通了,不等于 ERPNext 能稳定处理 50 人并发开单、不等于财务凭证能准确生成、更不等于 HR 模块的考勤计算不会因时区错位而多扣半天工资。Ubuntu 20.04 作为 LTS 版本,系统级组件(比如 systemd、glibc、openssl)版本相对保守,而 ERPNext v14+ 对 Node.js 16/18 和 MariaDB 10.5+ 有明确依赖,这就埋下了三类典型断点:一是
npm install
卡在
node-gyp rebuild
(因为 Ubuntu 默认没装 Python3-dev 和 build-essential);二是 MariaDB 启动失败,报
InnoDB: Unable to lock ./ibdata1 error
(因为 Ubuntu 20.04 的 AppArmor 策略默认限制 MySQL 数据目录访问);三是 Bench 初始化后
bench setup production
报
Permission denied: '/etc/nginx/conf.d/erpnext.conf'
(因为脚本试图直接写入系统级 Nginx 配置,但当前用户没加到 www-data 组)。
所以这篇内容不是教你怎么“一键安装”,而是带你亲手把 ERPNext 的整个技术栈像拆解一台机械表一样,一颗螺丝一颗螺丝地拧紧。我会告诉你:为什么必须用
apt install mariadb-server
而不是
docker run -d mariadb
;为什么
nvm install 18.19.0
比
sudo apt install nodejs
更可靠;为什么
bench setup production
后还要手动检查
/etc/supervisor/conf.d/erpnext.conf
里的
user = frappe
是否真实存在;甚至包括如何用
journalctl -u mariadb -f
实时盯住数据库启动日志,而不是等
bench migrate
失败了才去翻错误堆栈。这些细节,官方文档不会写,社区帖子只会说“重装试试”,但它们恰恰是决定 ERPNext 是“能用”还是“敢用”的分水岭。
如果你正准备用 ERPNext 管理公司账目、员工薪资或客户合同,那么你不是在部署一个 Web 应用,而是在搭建企业数字神经系统的底层脉络。下面所有操作,都基于我在 7 个真实生产环境(含 2 个高并发制造场景)中反复验证过的路径,每一步都有明确意图、可验证结果和兜底方案。
2. 整体架构设计与技术选型逻辑:为什么拒绝 Docker、为什么坚持源码部署
ERPNext 官方确实提供了 Docker Compose 部署方案,GitHub 上也有大量
erpnext-docker
仓库。但我在给一家年营收 2.3 亿的五金制造企业做实施时,明确否决了容器化方案。原因很实在:他们的 ERPNext 需要直连车间 PLC 的 Modbus TCP 接口,要调用本地串口设备
/dev/ttyUSB0
,还要运行自定义的 Python 脚本定时抓取 CNC 机床的 OEE 数据。Docker 容器默认无法穿透宿主机的设备节点和 udev 规则,强行挂载不仅权限混乱,还会导致 Supervisor 无法正确管理 bench 进程生命周期——一旦
frappe-worker
崩溃,容器可能静默退出,而你根本收不到告警。
所以本方案采用 Bench 源码部署模式 ,这是 Frappe 团队官方推荐的生产环境部署方式,也是全球 80% 以上中大型 ERPNext 用户的选择。它的核心优势在于:
-
完全可控的进程树
:
supervisord直接管理frappe-web,frappe-worker,redis-server,node-socketio等全部子进程,每个进程的 PID、内存占用、重启策略一目了然; -
无缝的 Python 环境隔离
:Bench 为每个站点创建独立的 virtualenv,
pip install的包不会污染系统 Python,也避免了python3.8和python3.10共存时的dist-packages冲突; -
原生的系统服务集成
:
bench setup production会自动生成/etc/systemd/system/erpnext-bench-frappe-web.service,与 Ubuntu 20.04 的 systemd 深度绑定,sudo systemctl restart erpnext-bench-frappe-web就能精准重启 Web 层,无需docker-compose restart frappe-web这种黑盒操作。
至于 MariaDB,必须使用
apt install mariadb-server
而非 Docker,理由有三:
-
性能确定性
:ERPNext 的财务模块(如总账凭证生成)涉及大量 JOIN 和 GROUP BY,MariaDB 的查询优化器对物理磁盘 I/O 路径极其敏感。Docker 卷的 overlay2 文件系统会增加一层 I/O 延迟,在高并发记账场景下,
SELECT SUM(debit) FROMtabGL EntryWHERE posting_date BETWEEN '2024-01-01' AND '2024-12-31'可能慢 300ms,这在银行对账时就是致命卡顿; -
备份可靠性
:
mysqldump --single-transaction必须直连 mysqld socket(/var/run/mysqld/mysqld.sock),Docker 容器内执行该命令需额外配置 host network 或 volume 挂载,而bench backup命令内部调用的就是这个原生命令,任何网络层抽象都会破坏其原子性; -
安全合规基线
:等保 2.0 要求数据库审计日志必须落盘到独立分区。Ubuntu 20.04 的
/var/log/mysql默认挂载在根分区,我们可直接用logrotate配置按日切割并压缩归档;若用 Docker,就得在容器外再搭一套日志收集管道,徒增复杂度。
Node.js 的选择同样关键。Ubuntu 20.04 官方源里的
nodejs
包版本是 10.19.0,而 ERPNext v14 要求最低 Node.js 16.14.0。
sudo apt install nodejs
不仅版本过低,其二进制包还被 Debian/Ubuntu 维护者打了补丁(比如禁用
--inspect
调试参数),导致
bench setup socketio
后无法启用实时通知。因此我们采用
nvm(Node Version Manager)
方式安装:它不修改系统 PATH,不覆盖
/usr/bin/node
,所有 Node.js 版本和 npm 包都严格限定在
~/.nvm/versions/node/
下,
bench
命令执行时通过
nvm use
切换上下文,彻底规避系统级冲突。
最后强调一点:本方案全程不依赖
pip install frappe-bench
。Bench 工具本身必须从 GitHub 主干克隆,因为
pip install
安装的是 PyPI 上的冻结版本(v5.12.0),而 Ubuntu 20.04 的
git
版本(2.25.1)与最新 Bench 的 Git Hook 脚本存在兼容问题。我们直接
git clone https://github.com/frappe/bench.git
,然后
python3 -m pip install -e bench/
,以 editable 模式安装,确保所有
bench
子命令(如
bench setup nginx
)都能调用到最新修复的 shell 脚本逻辑。
3. 核心环境准备与依赖安装:从系统初始化到 Bench 创建
3.1 Ubuntu 20.04 系统预检与加固
在敲下任何
apt install
命令前,先执行三步系统级检查。这不是形式主义,而是避免后续 80% 的“安装失败”根源:
-
确认系统时间与时区 :ERPNext 的所有业务单据(采购订单、销售发票)都带精确到毫秒的时间戳,且默认使用系统时区。执行
timedatectl status,输出必须包含System clock synchronized: yes和Time zone: Asia/Shanghai (CST, +0800)。如果显示no,运行sudo timedatectl set-ntp on;如果时区错误,执行sudo timedatectl set-timezone Asia/Shanghai。曾有个客户因服务器时区设为UTC,导致每天凌晨 2 点自动生成的库存盘点单,时间戳比实际晚 8 小时,财务对账时发现整整一周的出入库记录全乱序。 -
检查 swap 分区大小 :ERPNext Bench 初始化需要编译大量 Python C 扩展(如
cryptography,psycopg2),内存峰值常超 2GB。Ubuntu 20.04 默认只配 2GB swap,但bench init过程中若物理内存不足,gcc编译会因 OOM Killer 杀死进程。执行free -h,确认Swap行数值 ≥ 4G。若不足,用以下命令扩容:
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 永久生效
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
-
验证 DNS 解析稳定性
:Bench 安装过程需从 GitHub、PyPI、npmjs.org 下载数百 MB 依赖。执行
nslookup github.com 8.8.8.8和nslookup pypi.org 114.114.114.114,确保响应时间 < 100ms。若超时,编辑/etc/systemd/resolved.conf,将DNS=行改为DNS=114.114.114.114 8.8.8.8,然后sudo systemctl restart systemd-resolved。
提示:执行完上述检查后,务必运行
sudo apt update && sudo apt full-upgrade -y升级所有系统包。特别注意systemd和openssl的更新,Ubuntu 20.04 的初始镜像中systemd245 版本存在一个已知 bug:当supervisord启动多个子进程时,systemd会错误地将frappe-worker的 PID 写入/run/supervisord.pid,导致bench restart失败。升级到systemd 245.4-4ubuntu3.22可彻底解决。
3.2 MariaDB 深度配置:超越默认安装的 5 项关键调优
sudo apt install mariadb-server
只是起点。默认配置对 ERPNext 是灾难性的:
innodb_buffer_pool_size
仅 128MB,
max_connections
为 151,
wait_timeout
28800 秒——这些值在测试环境尚可,但在生产环境会导致频繁连接池耗尽和 InnoDB 缓存命中率暴跌。以下是必须手动修改的
/etc/mysql/mariadb.conf.d/50-server.cnf
配置段:
[mysqld]
# 1. 内存分配:设为物理内存的 60%,但不超过 16GB
innodb_buffer_pool_size = 6G
# 2. 连接数:ERPNext 每个用户会维持至少 2 个长连接(Web + Worker)
max_connections = 500
# 3. 查询超时:避免慢查询拖垮整个 DB
wait_timeout = 300
interactive_timeout = 300
# 4. 日志策略:开启慢查询日志,阈值设为 1 秒
slow_query_log = ON
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
# 5. 安全加固:禁用符号链接,防止恶意文件读取
symbolic-links = OFF
修改后,执行
sudo systemctl restart mariadb
,然后用
mysql -u root -p
登录,逐条执行以下 SQL 初始化 ERPNext 所需的数据库权限:
-- 创建专用数据库用户,密码强度必须含大小写字母+数字+特殊字符
CREATE USER 'erpnext'@'localhost' IDENTIFIED BY 'P@ssw0rd!2024';
-- 创建 ERPNext 主数据库(注意:数据库名必须全小写,否则 Bench 会报错)
CREATE DATABASE `erpnext` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 授予所有权限,但仅限 localhost,禁止远程连接
GRANT ALL PRIVILEGES ON `erpnext`.* TO 'erpnext'@'localhost';
-- 刷新权限表
FLUSH PRIVILEGES;
注意:
utf8mb4是强制要求。ERPNext 的客户名称、产品描述字段允许存储 emoji 和生僻汉字(如“䶮”、“龘”),utf8编码仅支持 3 字节,会导致插入时报Incorrect string value错误。COLLATE utf8mb4_unicode_ci确保中文排序正确,比如“北京”会排在“上海”之前,而非按字节码乱序。
3.3 Node.js 与 npm 的精准安装:绕过 Ubuntu 源的版本陷阱
Ubuntu 20.04 的
apt
源中
nodejs
包是 10.x,
npm
是 6.x,而 ERPNext v14 明确要求 Node.js ≥ 16.14.0 且 npm ≥ 8.5.0。强行
sudo apt install nodejs=16.19.0
会触发
apt
的依赖冲突(因为
nodejs
16.x 依赖
libssl1.1
,而 Ubuntu 20.04 默认是
libssl1.1
,但某些更新会升级到
libssl3
)。最稳妥的方式是用 nvm:
# 安装 nvm(从官方 GitHub 获取最新安装脚本)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# 重新加载 shell 配置
source ~/.bashrc
# 查看可用 Node.js 版本
nvm list-remote | grep "v18\."
# 安装 v18.19.0(LTS 版本,ERPNext v14 官方认证)
nvm install 18.19.0
# 设为默认版本
nvm alias default 18.19.0
# 验证
node -v # 输出 v18.19.0
npm -v # 输出 9.9.2(nvm 自动匹配兼容 npm 版本)
关键点在于
nvm use 18.19.0
必须在
bench init
前执行。因为 Bench 的
setup.py
会调用
npm install
编译前端资源,若此时
node
命令指向系统
/usr/bin/node
(v10.19.0),
npm install
会因
SyntaxError: Unexpected token '?'
直接崩溃(v10 不支持可选链操作符)。
实操心得:
npm install过程中若卡在node-sass编译,别慌。这是正常现象——node-sass需要下载预编译的二进制文件,国内网络常超时。执行npm config set sass_binary_site https://npmmirror.com/mirrors/node-sass/切换淘宝镜像源,再重试即可。切勿用npm install --unsafe-perm强行跳过,那会导致 CSS 样式丢失。
3.4 Bench 初始化与站点创建:从空目录到可访问后台
现在进入核心环节。我们不再用官方一键脚本,而是分步执行,确保每一步都可验证:
# 创建专用用户(强烈建议!避免用 root 或普通用户)
sudo adduser --disabled-password --gecos "" erpnext
sudo usermod -aG sudo erpnext
sudo su - erpnext
# 安装 Python 依赖(Ubuntu 20.04 默认无 python3-dev)
sudo apt install -y python3-dev python3-setuptools python3-pip build-essential
# 克隆 Bench 仓库(必须用 git clone,不能 pip install)
git clone https://github.com/frappe/bench.git
cd bench
# 以 editable 模式安装,确保 bench 命令调用最新代码
python3 -m pip install -e .
# 初始化 Bench 环境(指定 Python 和 Node.js 版本)
bench init --frappe-branch version-14 frappe-bench
cd frappe-bench
# 安装 ERPNext App(从 GitHub 主干拉取,非 PyPI)
bench get-app erpnext https://github.com/frappe/erpnext
# 创建新站点(域名必须是合法 FQDN,不能用 localhost)
bench new-site erpnext.local --db-name erpnext --mariadb-root-password 'your_mariadb_root_pass' --admin-password 'admin123'
这里有几个极易踩坑的细节:
-
bench new-site的--db-name参数必须与 MariaDB 中创建的数据库名完全一致(全小写、无下划线),且--mariadb-root-password必须是你在mysql_secure_installation时设置的 root 密码,不是erpnext用户的密码; -
erpnext.local是站点域名,Bench 会自动在/etc/hosts中添加127.0.0.1 erpnext.local,但浏览器访问时必须输入https://erpnext.local(注意 https),因为 Bench 默认启用 SSL 重定向; -
--admin-password设置的是 ERPNext 后台登录密码,不是系统用户密码,它会被哈希后存入tabUser表。
初始化完成后,执行
bench setup production erpnext
。该命令会:
-
创建
frappe系统用户(UID 1001); -
将
frappe-bench目录所有权设为frappe:frappe; -
生成
/etc/nginx/conf.d/erpnext.conf; -
生成
/etc/supervisor/conf.d/erpnext.conf; -
重启
nginx和supervisor服务。
注意:
bench setup production必须由erpnext用户执行,且该用户必须在www-data组中(sudo usermod -aG www-data erpnext)。否则nginx无法读取frappe-bench/sites目录下的静态文件,访问时会返回 403 Forbidden。
4. 关键服务配置与启动验证:让 ERPNext 真正“活”起来
4.1 Nginx 配置深度解析:不只是反向代理
bench setup production
生成的
/etc/nginx/conf.d/erpnext.conf
是一个精巧的流量调度器,它把不同类型的请求分发到不同后端:
upstream erpnext-web {
server 127.0.0.1:8000; # frappe-web 进程监听 8000
}
upstream erpnext-socketio {
server 127.0.0.1:9000; # node-socketio 进程监听 9000
}
server {
listen 80;
server_name erpnext.local;
# 所有 HTTP 请求强制跳转 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name erpnext.local;
# SSL 证书路径(Bench 自动生成自签名证书)
ssl_certificate /home/erpnext/frappe-bench/config/erpnext.local.crt;
ssl_certificate_key /home/erpnext/frappe-bench/config/erpnext.local.key;
# 静态文件直接由 Nginx 服务,不经过 Python
location /assets {
alias /home/erpnext/frappe-bench/sites/assets;
expires 1y;
add_header Cache-Control "public, immutable";
}
# API 请求转发给 frappe-web
location / {
proxy_pass http://erpnext-web;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# WebSocket 请求转发给 socketio
location /socket.io {
proxy_pass http://erpnext-socketio;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
这个配置的关键在于
location /assets
块。ERPNext 的前端资源(CSS、JS、图片)全部打包在
sites/assets
目录下,Nginx 直接读取文件并返回,绕过了 Python 的 WSGI 层。实测表明,启用此配置后,首页加载时间从 3.2 秒降至 0.8 秒。若你看到页面样式错乱,第一反应不是重装,而是检查
ls -l /home/erpnext/frappe-bench/sites/assets
是否存在,以及
nginx
进程是否以
www-data
用户身份运行(
ps aux | grep nginx
)。
提示:若需使用正式 SSL 证书(如 Let's Encrypt),不要直接替换
*.crt和*.key文件。应执行sudo bench setup lets-encrypt erpnext.local,该命令会自动调用certbot获取证书,并更新 Nginx 配置中的路径。手动替换会导致bench setup production下次运行时被覆盖。
4.2 Supervisor 进程管理:看清每个服务的“心跳”
bench setup production
同时生成了
/etc/supervisor/conf.d/erpnext.conf
,它定义了 ERPNext 的全部后台进程:
[program:erpnext-web]
command=/home/erpnext/frappe-bench/env/bin/python /home/erpnext/frappe-bench/apps/frappe/frappe/utils/bench_helper.py frappe serve --port 8000
user=frappe
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/home/erpnext/frappe-bench/logs/web.log
environment=HOME="/home/erpnext",USER="frappe"
[program:erpnext-worker]
command=/home/erpnext/frappe-bench/env/bin/python /home/erpnext/frappe-bench/apps/frappe/frappe/utils/bench_helper.py frappe worker --queue default,long
user=frappe
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/home/erpnext/frappe-bench/logs/worker.log
environment=HOME="/home/erpnext",USER="frappe"
[program:erpnext-socketio]
command=/home/erpnext/frappe-bench/env/bin/node /home/erpnext/frappe-bench/apps/frappe/frappe/socketio_app.js
user=frappe
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/home/erpnext/frappe-bench/logs/socketio.log
environment=HOME="/home/erpnext",USER="frappe"
执行
sudo supervisorctl reread && sudo supervisorctl update
加载新配置,然后
sudo supervisorctl status
查看状态:
erpnext-socketio RUNNING pid 12345, uptime 0:05:23
erpnext-web RUNNING pid 12346, uptime 0:05:22
erpnext-worker RUNNING pid 12347, uptime 0:05:21
若某进程显示
STARTING
或
FATAL
,立刻用
sudo supervisorctl tail -f erpnext-web
实时查看日志。常见问题:
-
erpnext-web启动失败:通常是frappe-bench/apps/erpnext/erpnext/patches/v14_0/update_stock_ledger_entry_posting_time.py执行超时,因为 MariaDB 的innodb_buffer_pool_size太小,需调大后bench migrate; -
erpnext-worker无法启动:检查/home/erpnext/frappe-bench/env/lib/python3.8/site-packages/redis/是否存在,若缺失,执行bench setup requirements重装 Python 依赖; -
erpnext-socketio报Error: Cannot find module 'socket.io':说明npm install未完成,进入frappe-bench/apps/frappe/目录,手动执行npm install。
4.3 启动验证与首屏访问:从命令行到浏览器的完整链路
所有服务就绪后,执行终极验证:
-
检查端口监听
:
sudo ss -tuln | grep ':80\|:443\|:8000\|:9000',应看到nginx监听 80/443,frappe-web监听 8000,node-socketio监听 9000; -
验证数据库连接
:
bench --site erpnext.local doctor,输出应为OK; -
测试 API 健康
:
curl -k https://erpnext.local/api/method/ping,返回{"message": "pong"}; -
浏览器访问
:打开
https://erpnext.local,首次加载会较慢(约 15-20 秒),因为 Nginx 正在缓存静态资源。登录用户名Administrator,密码为你创建站点时设置的--admin-password。
成功进入后台后,立即执行
bench --site erpnext.local set-admin-password 'NewStrongPass@2024'
修改管理员密码,并在
Setup > Company
中创建你的第一家公司。此时 ERPNext 已不再是“安装完成”,而是真正进入了业务可用状态。
实操心得:若浏览器打开空白页,90% 是
nginx配置未生效。执行sudo nginx -t验证语法,若报错nginx: [emerg] unknown directive "http2",说明你的nginx版本低于 1.9.5(Ubuntu 20.04 默认 1.18.0,已支持)。此时只需sudo systemctl restart nginx即可,无需降级。
5. 常见问题排查与独家避坑指南:那些官方文档绝不会写的细节
5.1 “bench migrate 报错:Table ‘tabUser’ doesn’t exist”
这是新手最高频的错误。表面看是数据库表缺失,实则是 Bench 初始化时
frappe
数据库未正确创建。根本原因在于:
bench new-site
命令执行时,Bench 会尝试连接
root
用户创建
erpnext
数据库,但如果 MariaDB 的
root
用户密码为空(即
mysql -u root
可直接登录),Bench 会因权限不足而静默失败,后续
bench migrate
就找不到基础表。
排查步骤 :
-
mysql -u root -p登录 MariaDB,执行SHOW DATABASES;,确认erpnext数据库是否存在; -
若不存在,手动执行
CREATE DATABASE \erpnext` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;`; -
然后
bench --site erpnext.local migrate。
预防方案
:在
bench new-site
前,确保
mysql_secure_installation
已运行,并为
root
用户设置了强密码。Bench 的
--mariadb-root-password
参数必须与之完全一致。
5.2 “npm install 报错:gyp ERR! stack Error: Can't find Python executable”
Ubuntu 20.04 默认安装
python3
,但
node-gyp
编译工具默认找
python
命令(指向
python2.7
)。虽然
python2.7
已废弃,但
node-gyp
的配置未更新。
解决方案 :
# 告诉 node-gyp 使用 python3
npm config set python /usr/bin/python3
# 或全局设置(推荐)
export PYTHON=/usr/bin/python3
# 然后重试 bench setup requirements
bench setup requirements
注意:
export PYTHON必须在bench init和bench setup requirements的同一 shell 会话中执行,否则 Bench 的子进程无法继承该环境变量。
5.3 “ERPNext 后台登录后白屏,控制台报 WebSocket connection failed”
这是
nginx
的 WebSocket 配置未生效的典型表现。
bench setup production
生成的配置中,
location /socket.io
块必须包含
proxy_http_version 1.1
和
proxy_set_header Upgrade $http_upgrade
,否则 Nginx 会把 WebSocket 升级请求当作普通 HTTP 处理,返回 400 Bad Request。
验证方法 :
-
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" https://erpnext.local/socket.io/?EIO=4&transport=websocket; -
若返回
HTTP/2 400,说明 Nginx 未正确处理 Upgrade; -
检查
/etc/nginx/conf.d/erpnext.conf,确认location /socket.io块中proxy_http_version和proxy_set_header两行存在且拼写正确; -
sudo nginx -t && sudo systemctl reload nginx。
5.4 “财务报表导出 Excel 时提示 ‘No module named xlsxwriter’”
ERPNext 的 Excel 导出功能依赖
xlsxwriter
Python 包,但
bench setup requirements
默认不安装它,因为它是可选依赖。
解决命令 :
# 切换到 bench 环境
cd /home/erpnext/frappe-bench
# 激活虚拟环境
source env/bin/activate
# 手动安装
pip install xlsxwriter
# 重启 web 进程
bench restart
独家技巧:若你经常导出大报表(>10万行),建议同时安装
openpyxl:pip install openpyxl。xlsxwriter速度快但不支持公式,openpyxl支持公式但内存占用高,Bench 会自动根据场景选择最优引擎。
5.5 “系统日志爆满:/var/log/supervisor/erpnext-web-stderr---supervisor-xxxxx.log 占用 20GB”
Supervisor 默认将所有进程 stderr 无限追加到单个日志文件,而 ERPNext 的
frappe-worker
在处理大批量数据(如导入 10 万条客户)时,会高频打印
INFO
级日志,几天就能撑爆磁盘。
永久解决方案
:
编辑
/etc/supervisor/conf.d/erpnext.conf
,在每个
[program]
块下添加:
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5
stderr_logfile_maxbytes=10MB
stderr_logfile_backups=5
然后
sudo supervisorctl reread && sudo supervisorctl update
。这样每个日志文件最大 10MB,保留 5 个备份,总占用不超过 100MB。
最后分享一个小技巧:ERPNext 的
bench命令其实自带调试开关。当你遇到任何奇怪问题,不要急着重装,先执行bench --verbose --site erpnext.local migrate,加上--verbose参数,它会输出每一行 SQL 执行过程和 Python 堆栈,90% 的问题都能在日志里定位到具体哪一行代码出了问题。这才是真正的“可运维”——不是靠运气,而是靠确定性。
421

被折叠的 条评论
为什么被折叠?



