ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

GoodERP(Odoo16)生产部署指南:版本兼容、服务常驻与排错

GoodERP(Odoo16)生产部署指南:版本兼容、服务常驻与排错

简介:这是一份面向 Odoo 初学者与实施顾问的 Odoo 16 实施应用指南,以在国内使用较多的 GoodERP(Odoo 中国版)为主线,帮助读者解决从基础资料配置到业务流程跑通的入门问题,适合刚接触开源 ERP、希望快速上手实操或者准备承担企业内部实施工作的人群学习和使用。资源包内只有 1 个 PDF 文件,整体约 9.01MB,属于手册式长文档,便于在电脑或平板上翻阅检索。内容覆盖系统权限与公司信息设置、客户供应商与商品计量单位等基础资料维护,以及采购、销售、仓库出入库的完整流转;还进一步收录了组装生产与委外、复杂工序与工序质检、MRP 分析、外贸多币种、权限隔离等进阶场景,并附有 Windows 与 Ubuntu 环境安装、Nginx 优化、PostgreSQL 调优和数据库管理等部署要点,可当作日常查阅的实施参考手册。目前已有 276 人学习。

1. Odoo16 实施应用的第一道坎:不是缺软件,是版本对不上

Odoo16 实施应用这件事,入门阶段最难啃的往往不是业务流程,而是把它装起来。我见过太多人在这一步翻车:照着帖子在服务器上敲了一下午pip install,最后卡在 psycopg2 编译报错;或者图省事下了 Windows 一键包,装完发现中文 PDF 打出来全是方块,两三个人同时登录就开始转圈。GoodERP 是基于 Odoo16 的中国化发行版,它本质上是一套 Python + PostgreSQL + Nginx 的组合服务,不是一个双击就能用的软件。装的时候顺序错一步、版本差一个号、认证方式没对上,后面所有配置工作都变成补窟窿。这篇按我实际部署的顺序走一遍:先定版本、建用户和库,再装源码、写配置、挂 systemd 和 Nginx,最后落到基础资料和跑通验证。第一次上手的人能照着走完,装过一次没跑通的人也能看清每一步到底在干什么。

2. 环境先列清:Ubuntu 22.04、PostgreSQL 15、Python 3.10 的版本取舍

装 Odoo 这件事,最容易翻车的不是命令敲错,而是版本组合本身就不成立。Odoo16 发布时的目标运行环境是 Python 3.10,大量依赖(psycopg2、lxml、Pillow)在 3.11 以上经常需要现场编译,运气不好就卡在某个 C 扩展上。Ubuntu 22.04 自带 Python 3.10,是我目前最省事的底座;24.04 自带 3.12,不是不能跑,是要多花半小时处理轮子问题。数据库这边,Odoo16 官方支持 PostgreSQL 12 以上,Ubuntu 22.04 apt 源里默认就是 14,单独装 15 也行,但 15 默认用 scram-sha-256 认证,配置文件和pg_hba.conf不对上就会一直报认证失败。

2.1 一张表把版本定下来

先别急着敲命令,把下面这张表对着自己的机器核一遍,尤其注意 wkhtmltopdf 那一行——它是 PDF 报表打印失败的头号原因。

组件推荐版本为什么是它
操作系统Ubuntu 22.04 LTS自带 Python 3.10,依赖包齐,社区资料最多
Python3.10Odoo16 的目标运行时,轮子基本都有预编译包
PostgreSQL14 或 15Odoo16 支持 12+;15 要注意认证方式是 scram-sha-256
wkhtmltopdf0.12.6 with patched Qtapt 源里的 0.12.5 不带 patched Qt,打印报表会空白或报 network error
Nginx1.18+反代静态资源、websocket 和 80 端口
Node.js / less可选只有改前端主题、自己编 scss 时才需要

需要说明的是 Python 版本。有人觉得越新越好,直接上 3.12,结果psycopg2编译时缺头文件、lxml版本对不上,一路修下去很耗时间。GoodERP 的代码基线是 Odoo16,跟着它的基线走最省事,别在这种地方追新。

2.2 装系统依赖:漏一个包,后面就是玄学报错

依赖包一次装齐,比出问题再回头找强得多。下面这串命令里,libpq-dev是 psycopg2 编译必需的,libldap2-dev和libsasl2-dev影响 LDAP 相关功能,libjpeg-dev、libfreetype6-dev关系到图片处理和报表字体。

sudo apt update sudo apt install -y git python3-pip python3-dev python3-venv \ build-essential libpq-dev libxml2-dev libxslt1-dev zlib1g-dev \ libsasl2-dev libldap2-dev libssl-dev libffi-dev libjpeg-dev \ libfreetype6-dev libcairo2-dev \ postgresql postgresql-client nginx

build-essential提供 gcc 和 make,没有它 pip 编译任何 C 扩展都会失败。postgresql-client单独列出来是因为后面要用psql从 odoo 用户那边连库排查问题,只装服务端不装客户端的情况很常见。装完可以用python3 --version和psql --version各确认一遍,别默认 apt 装的就是你以为的版本。

中文字体是另一件事,很多人装完能登录、能建单,一到打印报价单或发票,PDF 里的中文全是方框,还以为是报表模板坏了。实际是服务器上没有中文字体,wkhtmltopdf 渲染时找不到字形。

sudo apt install -y fonts-noto-cjk fonts-wqy-zenhei fc-cache -fv # 刷新字体缓存,不执行这一步新装的字体可能不生效

然后单独处理 wkhtmltopdf。apt 源里那个 0.12.5 是不带 patched Qt 的版本,Odoo 的报表引擎依赖 patched Qt 的特定行为,用错版本会出现「PDF 只出第一页」「表格线丢失」「Exit with code 1 due to network error」。去官方归档里找 0.12.6.1 的 deb 包(文件名形如wkhtmltox_0.12.6.1-2.jammy_amd64.deb),本地安装并确认版本号里带 patched qt:

sudo apt install -y ./wkhtmltox_0.12.6.1-2.jammy_amd64.deb wkhtmltopdf --version # 输出里应该能看到 (with patched qt),没有这行就说明装错了包

2.3 建 odoo 系统用户和 PostgreSQL 角色

Odoo 不应该用 root 跑,也不应该用你的登录账号跑。单独建一个系统用户,代码、数据目录、日志的属主都归它,后面 systemd 里User=odoo才对得上。

# 建系统用户,家目录给到 /opt/odoo,-r 表示系统账号不创建登录密码 sudo adduser --system --home=/opt/odoo --group odoo # 建数据库角色,--createdb 是必须的,Odoo 建库时要用 sudo -u postgres createuser --createdb odoo sudo -u postgres psql -c "ALTER USER odoo WITH PASSWORD '换成你自己的长密码';"

--createdb这个参数别省。Odoo 在网页上点「创建数据库」时,是用配置里的 db_user 去执行CREATE DATABASE,角色没有建库权限就会直接报权限错误,而这个错误在网页上只显示一句很含糊的提示,很难往权限方向想。

认证方式也要一起改。Ubuntu 上 PostgreSQL 默认对本地连接用 peer 认证,意思是系统用户名必须和数据库角色名一致,而我们的系统用户叫 odoo、角色也叫 odoo,本地 socket 能过,但 Odoo 走的是 TCP 127.0.0.1,peer 就不适用了,会落到 ident 或 md5 上。比较省事的做法是明确写成 scram-sha-256:

# /etc/postgresql/15/main/pg_hba.conf,注意路径里的版本号按实际改 local all odoo scram-sha-256 host all odoo 127.0.0.1/32 scram-sha-256

改完sudo systemctl reload postgresql,然后用psql -h 127.0.0.1 -U odoo -d postgres试一次,能进去说明账号和认证都通了。这一步验证过再往下走,能省掉后面一半的排查时间。

3. 安装与常驻:源码目录、odoo.conf、systemd、Nginx 四件套

环境齐了之后,剩下的是把 Odoo 变成一个「开机自启、崩了自动拉起、能从 80 端口访问」的服务。这中间有四样东西:代码目录、配置文件、systemd 单元、Nginx 站点。顺序别乱,先把 Odoo 在 8069 端口跑起来,再挂 Nginx,否则出问题时你分不清是 Odoo 没起来还是反代配错了。

3.1 目录约定和拉代码

目录结构建议一开始就定死,后面升级、加三方模块都靠它:

/opt/odoo/gooderp 代码主目录(odoo-bin 在这里) /opt/odoo/gooderp/addons 自带模块 /opt/odoo/custom-addons 三方模块,单独放,升级代码时不会被覆盖 /opt/odoo/.local/share/Odoo data_dir,附件和 session 都在这里 /var/log/odoo 日志目录 /etc/odoo.conf 配置文件

把三方模块和自带模块分开放,是血泪经验。每次git pull升级,自带模块目录会被覆盖,三方模块混在里面就得重新拷一遍,还容易漏。

sudo -u odoo git clone <项目方提供的 GoodERP 仓库地址> /opt/odoo/gooderp cd /opt/odoo/gooderp && sudo -u odoo git checkout 16.0 # 分支按项目方给的来 sudo mkdir -p /opt/odoo/custom-addons /var/log/odoo /opt/odoo/.local/share/Odoo sudo chown -R odoo:odoo /opt/odoo /var/log/odoo

拉完代码先看一眼odoo-bin是否存在、addons目录里有没有base、web这些基础模块,有就说明代码是完整的,缺了说明分支拉错了。

3.2 odoo.conf:十几个参数里真正要改的就那几个

配置文件不用抄一份上百行的模板,实际要动的就那么几项。下面这份是我一般会落地的最小可用版本:

[options] ; 数据库连接,这里的密码必须和 2.3 里 ALTER USER 设的一致 db_host = 127.0.0.1 db_port = 5432 db_user = odoo db_password = 换成你自己的长密码 db_name = False ; 数据目录,附件、session、filestore 都在这里,迁移时必须一起带走 data_dir = /opt/odoo/.local/share/Odoo ; 模块搜索路径,用逗号分隔,自带模块在前,三方模块在后 addons_path = /opt/odoo/gooderp/addons,/opt/odoo/custom-addons ; 日志 logfile = /var/log/odoo/odoo.log log_level = info ; 端口,Nginx 反代的目标 http_port = 8069 ; 生产必开:让 Odoo 信任 Nginx 传来的 X-Forwarded-* 头 proxy_mode = True ; 数据库管理器的主密码,装完就换成一串随机值,或者直接关掉管理器 admin_passwd = 换成一串二十位以上的随机字符串 list_db = False ; worker 相关,按 CPU 核数调整,4 核的机器大概是 9 workers = 9 max_cron_threads = 2 limit_memory_soft = 2147483648 limit_memory_hard = 2684354560 limit_time_cpu = 600 limit_time_real = 1200

几个参数值得单独说。proxy_mode = True如果漏了,表现是反代之后登录进去一会儿就掉线、后台显示的客户端 IP 全是 127.0.0.1、附件下载链接生成的是内网地址,很隐蔽。list_db = False关掉的是网页上的数据库管理器,那玩意儿暴露在公网等于把建库删库的入口挂出去,只留一个 master password 挡着并不稳妥。data_dir必须显式写,用默认值的话它会落在 odoo 用户的家目录下,后面换机器容易漏拷附件,客户说「系统里图片全挂了」就是这么来的。

3.3 systemd 托管:崩了自动拉起,日志别只盯终端

不要用nohup ./odoo-bin &这种方式跑生产。终端一关服务就没了,机器重启也不会自己起来。

# /etc/systemd/system/gooderp.service [Unit] Description=GoodERP (Odoo 16) After=network.target postgresql.service Requires=postgresql.service [Service] Type=simple User=odoo Group=odoo ExecStart=/usr/bin/python3 /opt/odoo/gooderp/odoo-bin -c /etc/odoo.conf Restart=always RestartSec=3 LimitNOFILE=65536 [Install] WantedBy=multi-user.target

Restart=always配上RestartSec=3,作用是进程异常退出后 3 秒重新拉起。Odoo 在内存吃紧时偶尔会被系统杀掉,有这个配置至少不用半夜手动重启。Requires=postgresql.service保证数据库先起,否则 Odoo 启动时连不上库会直接退出,虽然有 Restart 兜底,但会在日志里刷一堆误导性的连接错误。

sudo systemctl daemon-reload sudo systemctl enable --now gooderp sudo systemctl status gooderp --no-pager sudo tail -f /var/log/odoo/odoo.log

看到日志末尾出现HTTP service (werkzeug) running on 0.0.0.0:8069就说明服务起来了。这时候先用curl -I http://127.0.0.1:8069在本机测一下,返回 200 或 303 都算正常,再去配 Nginx。

3.4 Nginx upstream:把 8069 藏到 80 后面

前面挂 Nginx 有三个目的:省掉端口号、缓存静态资源、让 websocket 走得正常。Odoo16 这里有个版本差异要注意——16 开始原来的/longpolling换成了/websocket,反代如果不带Upgrade头,表现是页面能用但消息通知、聊天、部分实时刷新不工作,控制台里能看到 websocket 握手失败。

# /etc/nginx/conf.d/gooderp.conf upstream gooderp { server 127.0.0.1:8069 weight=1 fail_timeout=0; } server { listen 80; server_name _; client_max_body_size 100m; # 报表导出、大批量导入都慢,超时给足 proxy_read_timeout 720s; proxy_connect_timeout 720s; location / { proxy_pass http://gooderp; 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; proxy_redirect off; } # Odoo16 的实时通道,必须带 Upgrade 头 location /websocket { proxy_pass http://gooderp; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # 静态资源单独缓存,前端加载会快很多 location ~* /web/static/ { proxy_cache_valid 200 90m; proxy_buffering on; expires 864000; proxy_pass http://gooderp; } gzip on; gzip_types text/css text/plain text/xml application/xml application/javascript; }

client_max_body_size 100m是给附件上传留的余量,默认 1M 会让稍大的产品图或合同附件直接 413。proxy_set_header X-Forwarded-Proto这行在将来上 HTTPS 时必须对,否则 Odoo 生成的链接还是 http,混合内容会被浏览器拦掉。

sudo nginx -t # 先测语法,别直接 reload sudo systemctl reload nginx

提示:改完 Nginx 一定先nginx -t。语法错了 reload 会失败但旧配置还在跑,你会以为改动生效了,实际什么都没变。

3.5 workers 和预读:多核不是把数字调大就行

单进程模式下 Odoo 一次只能处理一个请求,两个人同时点保存,第二个人就得等。开 workers 才能用上多核,但数字不是越大越好,每个 worker 都是独立 Python 进程,都要占内存。常见做法是CPU 核数 × 2 + 1,4 核给 9,8 核给 17,同时用limit_memory_soft和limit_memory_hard卡住单进程内存,超了自动回收。

文件读取这块可以顺手调一下块设备预读值,对小文件密集读取(Odoo 加载大量 Python 模块和静态资源)有实际帮助:

# 查看当前值,一般是 128 cat /sys/block/vda/queue/read_ahead_kb # 调到 4096 echo 4096 | sudo tee /sys/block/vda/queue/read_ahead_kb

设备名按lsblk的实际输出改,云主机上常见的是 vda 或 sda。这是内核参数,重启失效,要持久化得写进 udev 规则或者开机脚本里,别调完就忘了。

数据库和应用分机部署也是同一个思路:把db_host指向数据库服务器 IP,pg_hba.conf放行应用服务器网段。这么做的收益是 CPU 和内存互不抢,但前提是两台机器之间延迟足够低,同机房内网没问题,跨地域就别折腾了,每次查询多几毫秒,页面一多就是肉眼可见的慢。

3.6 Windows 一键包:本地演示可以,别拿去上生产

项目文档里也给了 Windows 下的用法,一般是打包好的安装程序,自带 PostgreSQL 和 Python 运行时,装完点图标就能开。拿来给业务同事演示流程、做培训环境完全够用。

它的局限也很明确:不能开多 worker,多用户并发一上来就卡;服务注册需要管理员权限,普通账号装完经常出现「服务启动了但端口没监听」;安装路径里带中文或空格,某些模块加载会直接失败。我一般只在本地做功能和界面演示时用它,真要给一个部门用,还是走 Ubuntu 那套。

4. 初始化与基础资料:建库、管理员、科目、币种按顺序来

服务跑起来只是空壳,接下来这一步才是「实施」真正开始的地方。基础资料的录入顺序是有讲究的,顺序错了会出现「类别建好了但过账没科目」「客户建好了但订单下不了」这类问题,回头改很麻烦。我一般按:公司信息 → 会计科目与类别 → 币种 → 计量单位与属性 → 客户供应商 → 用户权限,这个顺序走。

4.1 首次建库:数据库管理器用完就锁

浏览器打开http://服务器IP,第一次会跳转到数据库管理页面,要求输入 master password,也就是配置文件里的admin_passwd。填库名、选语言、设置管理员密码,演示数据那一项不要勾——勾了会灌入一堆示例客户和产品,正式上线前清理起来很烦。

建库过程中如果卡住不动,八成是 db_user 没建库权限,或者认证方式没对上,回到 2.3 那一步检查。建完库立刻做两件事:把admin_passwd换成随机长串,把list_db设成 False 并重启服务。数据库管理器挂在公网上,等于把「删除数据库」的按钮开放给所有人,只靠一个密码挡着不合适。

4.2 管理员与用户权限:库管、采购、销售、出纳怎么分

系统默认的 Administrator 拥有全部权限。实际实施时,第一步是给它改个复杂密码,然后按岗位建普通用户:采购员、销售员、库管员、出纳、会计,一个岗位一个账号,不要多人共用一个。

在「配置 → 用户」里点创建,登录名建议用手机号或姓名全拼,因为这个字段就是登录账号,后期改起来牵扯的东西多。权限靠勾选权限组来控制,勾完保存,再通过「动作」下拉菜单里的「更改密码」设置初始密码。只有拥有配置权限的用户,登录后主菜单里才会出现「配置」入口,看不到这个菜单不是系统坏了,是权限没给。

4.3 公司信息与「根据发票确认应收应付」这个开关

「配置 → 高级配置 → 公司」里填名称、地址、税号,重点在「会计属性」页签:进项税税率、销项税税率、开户行三个字段必须先填对,它们会带到每一张单据上。开户行要先在「资金 → 设置 → 账户」里建好对公账户,才能在这里选到。

同一页签里有个开关叫「根据发票确认应收应付」,勾不勾区别很大。不勾的话,销售订单发货就产生应收;勾上之后,发货只是出库,还得去「资金 → 结算单」里对结算单做确认,才会生成应收。前者适合单据量小、流程简单的场景,后者更贴近有开票环节的实际财务流程。这个开关一旦有业务数据了再改,历史单据的应收应付会对不上,实施阶段就要和财务确认清楚。

资金账户还有个细节:录入期初余额时,系统会自动创建一张其他收入单和一张会计凭证来记录,不会静悄悄改余额。所以期初数据最好在正式启用前一次性录完,中途补录会产生一堆需要解释的凭证。

4.4 类别必须挂会计科目,否则后面全是空凭证

「配置 → 基本配置 → 类别」里维护客户、供应商、产品的分类。这一步看起来是纯整理工作,实际是整个账务的地基:每个类别都要选会计科目,产品卖出去记哪个收入科目、采购进来记哪个成本科目,全靠这里。

漏了会怎样?单据能建、能确认、能发货,一切看起来正常,直到会计去查凭证,发现借贷方科目是空的,或者全挤在默认科目上。这种问题在月底结账时才暴露,返工量很大。

库存那边还有一处:其他入库单、其他出库单用的收发类别,类型要选「核算」并指定对应科目,否则这类单据过账不产生凭证。

4.5 多币种:币种跟着科目走,这是个硬约束

GoodERP 的多币种实现方式和很多人预期的不一样:币种不是挂在客户上,而是跟着会计科目走。流程是先在科目上选币种,再把这个科目用到客户分类上,这个分类下的客户订单自然就是那个币种。

启用币种 → 给外币科目指定币种 → 客户分类关联该科目 → 客户归属该分类 → 订单币种确定

这里有个明确的限制要提前跟业务说清楚:同一客户不支持多币种交易。如果一家客户既有美元单又有人民币单,只能拆成两个客户档案,或者用不同的分类去承接。很多人在实施中途才发现这一点,那时候客户档案和 histor 单据都已经建了一堆,改起来非常难受。有外贸业务的,币种和分类方案要在录入客户之前定死。

4.6 三方模块:web_responsive 的装法与升级姿势

Odoo 生态里三方模块很多,装法都一样:把模块目录放进custom-addons,重启服务,开发者模式里更新应用列表,再搜索安装。拿界面适配的web_responsive举例:

# 解压到 custom-addons,注意目录层级,必须是 custom-addons/web_responsive/__manifest__.py sudo -u odoo unzip web_responsive.zip -d /opt/odoo/custom-addons/ sudo chown -R odoo:odoo /opt/odoo/custom-addons/web_responsive sudo systemctl restart gooderp

然后在浏览器地址栏把 URL 里的web后面加上?debug=1进入开发者模式,打开「应用 → 更新应用列表」,搜模块名安装。装完没反应,先确认__manifest__.py里的depends依赖模块是否都已安装,再确认addons_path里确实包含了 custom-addons 这个路径。

模块升级走命令行更可靠,尤其是批量升级:

sudo systemctl stop gooderp sudo -u odoo git -C /opt/odoo/gooderp pull # -u 指定要升级的模块,all 表示全部;--stop-after-init 让它跑完就退出,不要常驻 sudo -u odoo /usr/bin/python3 /opt/odoo/gooderp/odoo-bin -c /etc/odoo.conf -d 你的库名 -u all --stop-after-init sudo systemctl start gooderp

--stop-after-init这个参数别漏,不加的话升级完进程会挂在终端前台,你以为卡死了其实是在正常监听。升级前一定先pg_dump备份一份,升级中途报错留下半升级状态的库,处理起来很麻烦。

5. 排查:GoodERP 装完起不来的五个现场

安装过程中遇到的报错,来来回回就那么几类。下面这五条是我实际处理频率最高的,按「现象 → 原因 → 解决」记一遍,下次遇到能直接对上号。

5.1 现象:浏览器 502,日志里 psycopg2 连接被拒

现象是 Nginx 返回 502 Bad Gateway,/var/log/odoo/odoo.log里反复出现psycopg2.OperationalError: connection refused或no pg_hba.conf entry。

原因基本是两个:PostgreSQL 没启动,或者pg_hba.conf里没有放行127.0.0.1的 odoo 用户。Ubuntu 装完 PG 后默认监听 localhost,但如果配置文件里listen_addresses被改过,TCP 连接就进不来。

解决:先sudo systemctl status postgresql确认服务在跑,再psql -h 127.0.0.1 -U odoo -d postgres手动连一次,报什么错一目了然。认证问题就按 2.3 补pg_hba.conf,改完systemctl reload postgresql,不用重启整个服务。

5.2 现象:页面能开但样式全丢,菜单挤成一团

现象是登录页能打开,登录进去后界面没有配色、按钮错位、图标全是方块,浏览器控制台里一堆/web/static/的 404。

原因通常是 Nginx 的静态资源 location 写错,或者 Odoo 的 assets 缓存坏了。前者多见于location ~* /web/static/这条规则和主location /的匹配顺序冲突,后者常见于升级模块之后。

解决:先看 Nginx access log 里/web/static的请求是不是 404,是就检查反代规则;如果请求是 200 但内容不对,就停服务删掉data_dir下的 assets 缓存目录再启动,让 Odoo 重新打包前端资源。

5.3 现象:打印单据报 network error,或 PDF 里中文全是方块

现象是点打印报价单,页面上弹出Unable to find Wkhtmltopdf或Exit with code 1 due to network error;另一种是 PDF 能出,但中文变成一个个方框。

原因分别是 wkhtmltopdf 装的是不带 patched Qt 的 0.12.5 版本,以及服务器没装中文字体。

解决:wkhtmltopdf --version看输出里有没有(with patched qt),没有就换成 0.12.6.1 的包重装;中文方块就装fonts-noto-cjk并fc-cache -fv刷缓存,然后重启 Odoo 服务让新字体生效。顺带一提,字体装完不重启服务也有效,但打印进程是 Odoo 拉起的,重启最保险。

5.4 现象:模块目录放进去了,应用列表里搜不到

现象是三方模块已经解压到custom-addons,重启服务、更新应用列表、去掉「应用」筛选,还是搜不到这个模块。

原因有三种:目录层级多套了一层(变成custom-addons/web_responsive/web_responsive/),addons_path里没写这个路径,或者模块的depends里有未安装的依赖导致加载被跳过。

解决:先用ls custom-addons/模块名/__manifest__.py确认文件在正确层级,再systemctl cat gooderp看启动参数里的配置文件路径对不对,最后看日志里有没有这个模块的加载报错——依赖缺失会在日志里明确写出缺哪个模块。

5.5 现象:开多 worker 后定时任务重复执行、会话莫名丢失

现象是workers调大之后,某些自动任务一天跑了好几次,或者用户登录后过一会儿就被踢回登录页。

原因是proxy_mode没开,Odoo 拿不到真实客户端信息;另外多 worker 模式下每个进程各自处理 session,配置不当会互相覆盖。定时任务的重复执行,则常见于多个实例同时连一个库。

解决:确认proxy_mode = True;如果是异机部署或多实例,只让一个实例的max_cron_threads大于 0,其他实例设成 0,避免定时任务被多个进程同时抢。这个坑很隐蔽,刚开始只表现为「有些单据莫名其妙被处理了两次」。

6. 验证跑通:从建一张销售单开始,别只看首页能不能打开

装完看到登录页,很多人就认为大功告成了。首页能开只说明 HTTP 服务活着,跟业务能不能跑是两回事。我一般会走一遍完整链路,十几分钟,能把安装阶段八成的问题暴露出来。

第一步是命令层验证,三个检查点:

# 1. 服务状态,注意是 active (running) 而不是 activating systemctl is-active gooderp # 2. 端口监听,应该看到 127.0.0.1:8069 ss -lntp | grep 8069 # 3. 反代链路,从外网 IP 访问要能返回 200/303,不是 502 curl -I -H "Host: 你的域名或IP" http://127.0.0.1/

第二步是业务层验证,按最小闭环走一遍:建一个测试客户(类别选好、应收期初留空)→ 建一个测试商品(库存页签按需勾选管理批号或虚拟产品)→ 开一张销售订单并确认 → 点发货生成出库单 → 进「资金 → 结算单」确认 → 登记收款 → 回销售订单看状态是否变成「完成」。

这条链路里,建商品时如果勾了「虚拟产品」,发货不检查库存,适合电子版商品;勾了「管理批号」的实物商品,发货时必须填批次号,否则确认不了。这两个勾选项很容易被当成界面装饰随手勾上,后面卡在发货环节。

第三步是账务验证,用会计账号打开凭证列表,看刚才那笔销售有没有生成对应的应收凭证、科目是不是你在类别里配的那个。科目为空或者挂错,说明 4.4 那一步没做全。再顺手打一张报价单 PDF,确认中文正常、表格线完整。

第四步是并发验证,让两三个同事同时登录,各开各的单据,看有没有互相踢下线、保存转圈。这一步能验出proxy_mode和 workers 配置是否正确,单人测试永远发现不了。

注意:验证用的测试数据在正式启用前要清理干净,尤其是测试客户和测试商品,它们会带着期初余额和库存流水,混在正式数据里很难区分。

从那以后我每次装完 Odoo 都强制走一遍这条链路,不管这台机器是演示用还是生产用,也不管之前装过多少台。因为安装阶段留下的问题不会立刻爆发,往往等业务跑了两周、单据堆起来之后才冒出来,那时候再回头查配置,成本完全不是一回事。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进