news 2026/9/11 2:31:22

Rocky Linux生产环境部署Odoo:从系统初始化到Nginx反向代理全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rocky Linux生产环境部署Odoo:从系统初始化到Nginx反向代理全指南

1. 为什么我把Odoo生产环境从Ubuntu迁到了Rocky Linux

1.1 一次升级事故逼出来的选型反思

先说个真实经历。前两年我给一家做外贸的公司维护过一套跑在Ubuntu 18.04上的Odoo,平时挺稳定,结果有一回系统提示可以做LTS升级,我没多想就点了,升级过程中PostgreSQL从10被强制迁移到12,Python环境也被系统包管理器动了手脚,结果Odoo服务起不来,数据库连接报错,客户那边销售单录到一半卡住,电话直接打到我手机上。那次折腾了将近一天才恢复,教训特别深刻:跑企业级应用的服务器,稳定性要比“新”重要得多。

后来我接了一个新项目,客户要求重新搭一套Odoo,我毫不犹豫选了Rocky Linux。这不是拍脑袋的决定。Rocky Linux是CentOS停止维护之后最被看好的替代品之一,走的是RHEL兼容路线,社区维护活跃,而且它不搞Ubuntu那种激进升级策略,每个大版本的生命周期很长,补丁风格偏保守。对ERP这种不能随便宕机的应用来说,这种“慢工出细活”的节奏反而最合适。

这套部署方案适合谁?我总结下来主要是三类场景:一是要给中小型制造或贸易企业搭一套内部可用的ERP系统,二是个人想系统学习Odoo在生产环境中的完整落地流程,三是做Odoo实施服务的团队需要一套可复现的交付模板。后面我会把所有步骤拆开讲,包括为什么这么做、参数怎么算、哪些坑我替你踩过了。

1.2 Rocky Linux在企业环境里的几个实在优势

对比Debian系,Rocky Linux在企业部署中的好处非常具体。

首先是生命周期。Rocky Linux 9的支持周期到2032年,8系列甚至更久,这意味着你在一台服务器上部署完后,几年内不需要因为系统版本到寿而被迫迁移。ERP数据迁移是大工程,能不动就不动,这一点对企业IT负责人来说几乎是刚需。

其次是生态兼容性。RHEL系是商业软件适配的重灾区,各种商业数据库、中间件、安全软件都会优先出RHEL兼容版本。Rocky Linux既然和RHEL二进制兼容,那这些闭源组件(比如某些财务接口的SDK)装起来就很顺利。这一点在给客户做系统集成时特别省事。

第三个是软件包管理风格。dnf虽然初看比apt繁琐,但模块化机制(dnf module)让你可以锁定PostgreSQL、Python这类基础软件的版本,避免系统升级时被悄悄改变。生产环境最怕的就是“悄悄变化”。

1.3 这套方案适合什么样的场景

注意,我说的是Rocky Linux做生产环境的底座,不代表所有Odoo场景都该这么搭。如果只是本地开发、快速试错,你直接跑Docker容器或者用Odoo官方的一键安装脚本就够了,没必要花时间做这套系统级部署。

但如果你遇到下面任意一种情况,就该用今天这套方案了:

  • 企业要求数据完全自主可控,不希望依赖第三方云平台的托管数据库。
  • 你需要在同一台服务器上对接内部AD/LDAP、做定制化模块开发、安装私有Python依赖。
  • 并发用户超过20人,需要相对精细地控制worker进程、数据库参数和反向代理行为。
  • 客户是制造或流通企业,对数据备份、审计日志、权限边界有比较明确的要求。

这套方案的核心理念是:每个组件都比“默认安装”多迈一步,所有服务都由systemd管理,所有日志都可回溯,所有配置都有注释。下面开始实操。

2. 系统初始化:静态IP、swap、防火墙一个都不能省

2.1 用nmcli配置静态IP,别再去改ifcfg-eth0了

很多人搜Rocky Linux教程时习惯找“修改/etc/sysconfig/network-scripts/ifcfg-eth0”这种老办法,但在Rocky 8/9里,NetworkManager接管了网络配置,直接改文件不仅麻烦,还容易因为格式错误导致网络起不来。正确姿势是用nmcli。

先看当前的网络连接名称:

nmcli connection show

假设网卡连接名是ens160,执行下面四条命令就能配置静态IP:

nmcli con mod ens160 ipv4.addresses 192.168.1.100/24 nmcli con mod ens160 ipv4.gateway 192.168.1.1 nmcli con mod ens160 ipv4.dns "8.8.8.8 114.114.114.114" nmcli con mod ens160 ipv4.method manual nmcli con up ens160

注意ipv4.method manual这一步最容易忽略。不改成manual,重启网卡后系统可能又去DHCP拿地址,IP变了Odoo虽然还能用,但Nginx、PostgreSQL里如果是用IP做访问控制的,就直接瘫痪了。

检查一下配置是否生效:

ip addr show ens160 ping -c 3 gateway

还有个小细节:如果你的服务器在机房或云平台上,云平台控制台里也要绑定相同的私网IP,否则重启后云平台可能会把IP抢走。这个我在实际项目中遇到过,花了不少时间才定位到是云平台和系统配置冲突。

2.2 swap规划:4GB内存的服务器硬跑Odoo会怎样

Odoo对内存的胃口不小。跑一个15个并发用户的测试环境,光PostgreSQL加Odoo主进程,空闲状态下就要吃掉2GB左右,峰值翻倍很常见。如果服务器只有4GB内存,不配置swap,早晚会遇到OOM Killer把Odoo进程杀掉。

我的建议是:

  • 8GB以下内存的服务器,swap至少分配到物理内存的1.5倍。
  • 8GB以上,swap可以分到4GB即可,主要用于抵御突发峰值。

Rocky Linux下创建swapfile的方式:

fallocate -l 4G /swapfile chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo "/swapfile none swap sw 0 0" >> /etc/fstab

这里有个小坑:某些文件系统上fallocate创建的swapfile在swapon时会报“swapon failed: Invalid argument”。遇到这种情况不要慌,改用dd方式重建:

dd if=/dev/zero of=/swapfile bs=1M count=4096 chmod 600 /swapfile mkswap /swapfile swapon /swapfile

另外建议调整vm.swappiness。对数据库服务器来说,不要太早把进程往swap里赶:

echo "vm.swappiness = 10" >> /etc/sysctl.conf sysctl -p

2.3 firewalld这样开端口,SELinux这样设置

Rocky Linux默认开了firewalld和SELinux,这两个东西是新手最容易头大的,但千万别图省事直接关掉。企业交付时如果安全审计发现SELinux是disabled,很不好交代。

生产环境只需要对外开放80/443和SSH端口,Odoo的8069和8072端口不要暴露到公网,只让Nginx本机访问即可:

firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --permanent --add-service=ssh firewall-cmd --reload

SSH端口如果你改成了非默认端口,记得把--add-service=ssh换成--add-port=你的端口/tcp,不然防火墙一重载你把自己锁在门外就尴尬了。

SELinux方面,部署Odoo本身一般不需要额外设置,因为Odoo进程是自定义的,SELinux默认对它没有特殊限制。要特别注意的反而是Nginx,它做反向代理时默认不允许向后端发起网络连接,需要放行:

setsebool -P httpd_can_network_connect 1

如果忘了这一步,Nginx会频繁报502或超时,排查起来非常费劲。

2.4 时间同步和主机名这些“小”配置

时间同步对ERP系统非常重要,订单时间、库存流水时间、日志审计时间都得准确。Rocky默认装了chrony,确认它在运行就行:

systemctl status chronyd timedatectl set-timezone Asia/Shanghai

主机名也别忽略,PostgreSQL和Odoo日志里会出现主机名,如果主机名是随机的localhost,排查问题时会增加很多困惑:

hostnamectl set-hostname odoo-prod-01

改完顺便把/etc/hosts里的对应条目加上,避免某些服务解析主机名超时。

3. PostgreSQL:Odoo的数据底座怎么调才不拖后腿

3.1 安装和初始化,以及pg_hba.conf的认证坑

Rocky系列仓库里直接带了PostgreSQL,值得留意的是dnf模块流版本。建议锁定在PostgreSQL 13或14,Odoo官方支持得很充分。

dnf module list postgresql dnf module enable postgresql:13 -y dnf install -y postgresql-server postgresql-contrib

初始化数据库后启动:

postgresql-setup --initdb systemctl enable --now postgresql

这中间有个高频坑:默认的pg_hba.conf里,本地主机连接用的是ident认证方式,也就是系统用户名和数据库用户名必须一致,否则连接时直接报“no pg_hba.conf entry for host ...”。Odoo是用TCP连数据库的,必须改成MD5或SCRAM-SHA-256认证。

编辑/var/lib/pgsql/13/data/pg_hba.conf,把下面两行:

host all all 127.0.0.1/32 ident host all all ::1/128 ident

改成:

host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-256

同时确认/var/lib/pgsql/13/data/postgresql.confpassword_encryption设置为scram-sha-256,然后重启PostgreSQL:

systemctl restart postgresql

3.2 建库建用户,权限边界一定要划清楚

生产环境不建议直接用postgres超级用户跑Odoo,规范做法是在PostgreSQL里建专用的Odoo账号和数据库:

sudo -u postgres psql

进入psql后执行:

CREATE USER odoo WITH PASSWORD 'your_strong_password'; CREATE DATABASE odoo_prod OWNER odoo ENCODING 'UTF8'; GRANT ALL PRIVILEGES ON DATABASE odoo_prod TO odoo; \q

有两个容易忽略的点。第一,ENCODING 'UTF8'一定要显式指定,Odoo的很多多语言功能依赖UTF8,不指定可能继承模板库编码导致乱码。第二,如果后续你想用pgAdmin远程连这个库做管理,会需要给用户增加LOGIN权限,但生产环境我一般建议不开PostgreSQL远程端口,需要管理时通过SSH隧道连更安全。

3.3 生产级参数:shared_buffers、effective_cache_size到底设多少

很多教程让你照抄一组配置,但参数应该跟着服务器内存走。以一台8GB内存、16核CPU的服务器为例,我的经验基准是:

  • shared_buffers = 2GB:通常设置为总内存的25%左右。
  • effective_cache_size = 6GB:表示操作系统和PostgreSQL共享的缓存预算,设置为总内存的75%。
  • work_mem = 32MB:排序和哈希操作的内存上限。注意这是“每个操作”的预算,并发高的场景别给太大,否则内存直接被打满。
  • maintenance_work_mem = 256MB:用于VACUUM、CREATE INDEX等维护操作。
  • max_connections = 200:Odoo的worker进程数一般不会很多,但加上其他管理连接,200够用。
  • wal_level = replicamax_wal_senders = 10:提前为后续做主从复制留好余地。
  • checkpoint_completion_target = 0.9:分散检查点的I/O压力。

改完配置后重启PostgreSQL,然后看实际占用的内存:

ps aux | grep postgres

如果shared_buffers设得过高,加上Odoo worker的内存,8GB机器很容易吃紧。参数不是越大越好,够用就行。

3.4 备份要在没出事之前就演练过

我见过太多人部署完从来没测过恢复,等到数据库挂了才发现backup脚本一直在报错。生产环境必须做两件事:定时备份,以及定期恢复演练。

最简单的逻辑备份命令:

sudo -u postgres pg_dump -F c -b -f /backup/odoo_prod_$(date +%F).dump odoo_prod

-F c表示自定义格式,-b包含大对象(Odoo附件存储会用到大对象,这个参数必须加)。恢复也很直接:

sudo -u postgres pg_restore -d odoo_restore /backup/odoo_prod_某天.dump

备份老司机都知道,数据库备份只是半个备份,Odoo上传的文件都存在data_dir的filestore目录里,所以完整备份一定把两者打成一个包,后面第6节我会给出完整的定时脚本。

4. Odoo本体安装:源码、RPM、Docker三种路线怎么选

4.1 三种安装方式的真实差异

网上搜Odoo安装教程,你会看到三种主流方式:Odoo官方RPM包、Docker Compose、源码运行。直接说我的结论:生产环境优先选源码部署。

官方RPM包的问题是版本相对滞后,而且默认安装路径和文件布局是按他们内部打包逻辑来的,你后续想自定义模块、调整Python依赖时就比较别扭。Docker Compose胜在干净,一条命令拉起来,但问题也明显:数据卷、容器日志、网络模式对运维能力要求反而更高,数据库容器状态不好排查,真要出问题时,Docker的故障域比裸机更难界定。源码部署看起来最麻烦,但每一步都是自己控制的,模块路径清晰、日志明确、性能可调,出了问题也最容易定位。

当然,开发机或测试环境直接Docker最快,我不反对。

4.2 源码部署完整步骤(我推荐的方式)

先装编译依赖和工具链,Odoo的Python依赖里有很多C扩展:

dnf install -y git python3 python3-devel gcc libxml2-devel libxslt-devel libjpeg-turbo-devel freetype-devel openldap-devel libffi-devel openssl-devel redhat-rpm-config

创建专用系统用户,不要用root跑Odoo:

useradd --system --home-dir /opt/odoo --shell /sbin/nologin odoo

拉取源码。Odoo 17是当前稳定版,也是我推荐生产环境使用的版本:

mkdir -p /opt/odoo git clone --depth 1 --branch 17.0 https://github.com/odoo/odoo.git /opt/odoo/odoo

--depth 1能减少下载量,但要注意:以后想升级分支时,可能需要先git fetch --unshallow才能拉到完整历史。如果想做源码级的定制,建议去掉--depth 1

创建Python虚拟环境并安装依赖:

cd /opt/odoo/odoo python3 -m venv /opt/odoo/venv /opt/odoo/venv/bin/pip install --upgrade pip /opt/odoo/venv/bin/pip install -r requirements.txt

如果服务器无法直接上外网,建议提前把requirements.txt里的包下载到内网源,不然这个步骤会卡很久。

创建数据和日志目录并修正权限:

mkdir -p /var/lib/odoo mkdir -p /var/log/odoo chown -R odoo:odoo /opt/odoo chown -R odoo:odoo /var/lib/odoo chown -R odoo:odoo /var/log/odoo

4.3 odoo.conf每个参数我都解释一遍

配置文件放在/etc/odoo.conf,内容如下,我逐段说明:

[options] addons_path = /opt/odoo/odoo/addons,/opt/odoo/addons data_dir = /var/lib/odoo admin_passwd = 换成超强随机密码 db_host = 127.0.0.1 db_port = 5432 db_user = odoo db_password = 和PostgreSQL里建的一致 db_name = odoo_prod list_db = False proxy_mode = True xmlrpc = True logfile = /var/log/odoo/odoo.log log_level = info workers = 4 max_cron_threads = 2 limit_time_cpu = 600 limit_time_real = 1200 limit_memory_hard = 2684354560 limit_memory_soft = 2147483648

几个重点参数:

  • list_db = False:关闭数据库列表接口,避免攻击者通过页面扫描可用的数据库名。这个在企业安全评估里很容易被扣分,建议直接设置。
  • proxy_mode = True:启用反向代理模式,Odoo会读取X-Forwarded-*头生成正确的链接。如果你用Nginx却不开这个,用户访问时可能看到端口号或者生成错误的URL。
  • workers:不是越大越好。经验公式是workers = 2 * CPU核心数 + 1,但还要受内存限制。8GB内存的机器设4个比较稳。
  • limit_memory_hardlimit_memory_soft:以字节为单位。2684354560是2.5GB,2147483648是2GB。建议根据你服务器的内存和worker数平衡一下。
  • max_cron_threads = 2:跑定时任务的线程数。别设太大,否则多个cron任务同时跑会把CPU瞬间拉满。

另外说下addons_path。源码版本里有两个addons目录:一个是内置模块,另一个是你的自定义模块目录。你可以先创建/opt/odoo/addons空目录,以后放定制模块。

4.4 systemd管理Odoo服务

创建/etc/systemd/system/odoo.service

[Unit] Description=Odoo ERP Requires=postgresql.service After=network.target postgresql.service [Service] Type=simple User=odoo Group=odoo ExecStart=/opt/odoo/venv/bin/python3 /opt/odoo/odoo/odoo-bin -c /etc/odoo.conf Restart=always RestartSec=5 KillMode=mixed [Install] WantedBy=multi-user.target

启动并验证:

systemctl daemon-reload systemctl enable --now odoo systemctl status odoo

KillMode=mixed这个参数值得提一下:它保证停止服务时先发SIGTERM给主进程,再发SIGKILL给残留的子进程,避免留下僵尸worker。我用默认的control-group模式时,偶尔会遇到服务停了但端口还被占用的情况,换成mixed后没再犯过。

如果你访问http://服务器IP:8069看到数据库管理页面,说明服务跑起来了。没有页面的话先看日志:

tail -f /var/log/odoo/odoo.log

大部分启动失败都能在日志里直接看到原因,最常见的是数据库密码不对、目录权限不足、Python依赖缺失。

4.5 LibreOffice必须装,否则报表全是空白

这一点特别容易被忽略。Odoo的QWeb报表最终是转成PDF输出的,而PDF转换依赖LibreOffice的无头模式(headless)。不装LibreOffice,你导出的销售订单、采购单、报价单都会是空白或者报“QWeb PDF generation failed”。

安装方式:

dnf install -y libreoffice-headless

装完建议手动跑一次命令验证库文件完整:

libreoffice --headless --version

如果显示版本号就说明正常。注意,如果你之前没有安装字体,中文PDF导出可能出现乱码,建议顺便装一下中文字体:

dnf install -y wqy-zenhei-fonts wqy-microhei-fonts

对于日文、韩文等文字,也需要对应安装字体包。

5. Nginx反向代理:把长轮询、WebSocket、HTTPS一次性搞定

5.1 Nginx安装及SELinux放行

安装Nginx:

dnf install -y nginx systemctl enable --now nginx

如果启动失败,先排查80端口是否被占用:

ss -lntp | grep :80

SELinux放行之前提过,httpd_can_network_connect一定要设置,否则Nginx代理到8069会直接Connection refused或者超时。怎么判断是不是SELinux?去看这个命令的输出:

ausearch -m avc -ts recent | grep nginx

有输出就说明是SELinux拦截了,执行了setsebool -P httpd_can_network_connect 1再验证。

5.2 SSL证书与安全头配置

我建议你直接用证书管理工具自动申请Let's Encrypt证书,也可以把已有的企业证书手动放到/etc/nginx/ssl/下面。手动部署证书的Nginx配置片段如下:

server { listen 80; server_name erp.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name erp.example.com; ssl_certificate /etc/nginx/ssl/erp.example.com.crt; ssl_certificate_key /etc/nginx/ssl/erp.example.com.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; }

X-Frame-Options记得设成SAMEORIGIN。Odoo的部分界面(比如看板视图里嵌入iframe)需要同源加载,如果设成DENY会导致某些视图显示不正常。

5.3 长轮询/WebSocket专用location

Odoo有一个常驻的聊天/消息推送服务,监听在8072端口,同时存在WebSocket和长轮询两种情况。如果Nginx配置里没有单独处理这两个路径,聊天消息会不实时刷新,讨论串收发异常,甚至消息丢失。

在刚才的443 server块中,额外加上:

location /longpolling/ { proxy_pass http://odoo_chat; 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_buffering off; proxy_connect_timeout 7200; proxy_read_timeout 7200; proxy_send_timeout 7200; } location /websocket/ { proxy_pass http://odoo_chat; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 7200; proxy_send_timeout 7200; proxy_buffering off; }

对应的upstream定义在http块中:

upstream odoo_web { server 127.0.0.1:8069; } upstream odoo_chat { server 127.0.0.1:8072; }

注意/longpolling/末尾的斜杠,别省略。我见过有人漏了斜杠导致路径拼接出错,刷新页面时总是404。

5.4 代理超时参数,别用默认值

默认的Nginx代理超时只有60秒,如果Odoo在处理一个大数据量报表或者批量导入,超过60秒就会直接返回504,用户看着页面转圈然后报错。经验是把超时时间拉长:

proxy_connect_timeout 7200; proxy_read_timeout 7200; proxy_send_timeout 7200;

同时还要关闭proxy_buffering。Odoo的聊天消息、进度条通知这类功能依赖实时响应,如果开了缓冲,数据会在Nginx层堆积,前端收到消息延迟明显。

改完配置先测试语法:

nginx -t systemctl reload nginx

6. 上线后的运维清单:日志、升级、备份恢复

6.1 日志分割与磁盘空间监控

Odoo默认把日志写到/var/log/odoo/odoo.log,不处理的话日志会越来越大,直到把磁盘塞满。用logrotate来做是最省事的方案。

创建/etc/logrotate.d/odoo

/var/log/odoo/*.log { daily rotate 14 compress missingok notifempty copytruncate }

其中的copytruncate很关键。如果直接kill -HUP当前进程,可能会让Odoo重新加载日志句柄失败,甚至日志不写。用copytruncate会把日志复制一份再清空原文件,应用完全感知不到,比较安全。

日志之外的磁盘监控,建议用zabbix或者简单的cron脚本检查df -h输出,一旦磁盘使用率超过85%就发告警。ERP的filestore目录很容易被附件塞满,这个真的发生过很多次。

6.2 升级Odoo的完整流程(先备份再动手)

升级Odoo不是简单git pull就完事。社区版每个minor版本之间也要走规范化流程,尤其是模块数据库结构有调整的时候。我现在的升级流程是:

  1. 停止Odoo服务:systemctl stop odoo
  2. 完整备份:数据库dump + filestore打包
  3. 拉取新代码:cd /opt/odoo/odoo && git pull origin 17.0
  4. 更新Python依赖:/opt/odoo/venv/bin/pip install -r requirements.txt
  5. 运行模块升级:sudo -u odoo /opt/odoo/venv/bin/python3 /opt/odoo/odoo/odoo-bin -c /etc/odoo.conf -d odoo_prod -u all --stop-after-init
  6. 启动服务:systemctl start odoo
  7. 验证核心业务:登录、录一张测试订单、跑一次报表、看聊天消息是否正常。

其中第5步很容易卡很久,因为-u all会触发所有已安装模块升级,生产库可能在几千张表上做结构变更,耗时取决于数据量,少则几分钟多则几小时。一定先在前一天的非工作时间安排这个窗口,别白天直接升。

如果升级后出现模块报错,眼睛要盯着两个地方:一是/var/log/odoo/odoo.log里的Traceback,二是/var/log/odoo/odoo.logModule xxx loaded是否都出现。有一次我遇到一个自定义模块依赖了旧接口,日志里直接报AttributeError,这种只能回滚代码再尝试。

6.3 数据库+filestore的备份还原演练

前面第3节说过,备份必须包含数据库和filestore两个部分。我现在用的完整备份脚本是这样:

#!/bin/bash # /usr/local/bin/backup_odoo.sh BACKUP_DIR=/backup DB_NAME=odoo_prod DATA_DIR=/var/lib/odoo DATE=$(date +%F_%H-%M) # 1. 数据库自定义格式备份 sudo -u postgres pg_dump -F c -b -f "$BACKUP_DIR/${DB_NAME}_${DATE}.dump" "$DB_NAME" # 2. filestore打包 tar czf "$BACKUP_DIR/filestore_${DATE}.tar.gz" -C /var/lib odoo # 3. 清理7天前的备份 find "$BACKUP_DIR" -name "*.dump" -mtime +7 -delete find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete

放进crontab:

0 2 * * * /usr/local/bin/backup_odoo.sh >/dev/null 2>&1

恢复的完整流程:

# 1. 创建新数据库 sudo -u postgres createdb -O odoo odoo_restore # 2. 恢复数据 sudo -u postgres pg_restore -d odoo_restore /backup/odoo_prod_某日.dump # 3. 恢复filestore sudo -u odoo tar xzf /backup/filestore_某日.tar.gz -C /var/lib # 4. 在odoo.conf中临时把db_name改成odoo_restore,然后启动服务验证

别只在文档里写恢复流程,建议每季度真刀真枪恢复一次到测试库,确认备份文件能跑通。我见过太多公司备份脚本运行了半年,结果恢复时报“archive file not found”这类低级问题。

7. 生产环境踩过的坑,今天一次性复盘

7.1 SELinux拦截导致502

有一次客户反馈网站打开502,我第一反应是Nginx配置问题,调了半小时都没解决。后来习惯性地去翻/var/log/audit/audit.log,发现一堆denied { name_connect } for pid=xxx comm="nginx"记录。原因就是新服务器装了Nginx后,没有执行setsebool -P httpd_can_network_connect 1

这个坑的特别之处在于:它不是必现的。有时Nginx的某些编译参数或配置会触发SELinux限制,有时不会,特别迷。所以我的建议是,在部署脚本里把setsebool直接写上,别等到出了问题再查。

7.2 OOM kill,内存预算怎么算

4GB内存的服务器跑了Odoo加PostgreSQL,worker设了8个,上线第二天早上客户发现系统很卡,查看/var/log/messages

grep -i "killed process" /var/log/messages

看到Out of memory: Killed process 12345 (odoo)。根本原因是worker数超过内存预算。Odoo每个worker进程大约占用150-250MB内存,8个worker加PostgreSQL的2GB shared_buffers,4GB机器肯定顶不住。

调整方式就是减少workers到2或3,同时降低limit_memory_hard。内存这个事一定要按“峰值”来算,不要按“空闲”来算。上线前建议用并发脚本做一轮压力测试,把20个用户同时操作录单的情况模拟一遍,观察内存峰值再定参数。

7.3 长轮询不工作,聊天消息像断线

还有一次客户反馈说,系统里两个同事同时编辑一张订单,A改了B那边不自动刷新,要手动刷新页面才能看到。这就是长轮询没走通的现象。

检查链路:浏览器请求/longpolling/→ Nginx代理到127.0.0.1:8072→ Odoo的gevent处理。我排查时发现Nginx配置里没有那段location /longpolling/,请求直接被代理到8069的Odoo主服务了。补上配置后,聊天和实时协作就正常了。

另外一个容易踩的坑是proxy_buffering没关。有人按网上的配置加了长轮询location但忘了关缓冲,结果消息延迟能达到几十秒甚至更久。这个参数对实时交互类功能至关重要。

7.4 升级后模块不兼容的排查思路

Odoo每次大版本升级都伴随大量模块接口变化。从16升17那会儿,很多第三方模块的JavaScript改写方式完全不同,升级后出问题概率很高。

我的排查步骤:

  1. odoo.log里第一个报错的模块名,一般就是问题源头。
  2. 找到这个插件的清单文件__manifest__.py,看声明的依赖版本范围。
  3. 检查插件目录里是否有旧API调用(比如fields.functionapi.one这种老写法)。
  4. 如果插件有Git仓库,直接看其master分支是否已适配新版Odoo,必要时升级插件而不是升级Odoo。

还有一个实用技巧:升级前先在一台测试机上用生产数据副本跑一遍-u all,把报错全部暴露在测试环境里,别在生产上直接试错。这个习惯帮我避免了好几次不可逆的数据库变更。

回到最初的话题,Rocky Linux + Odoo这套方案做到现在,我最大的体会是:ERP部署没有银弹,所谓的“企业级”不在用了多少新潮技术,而在每个环节都有人想过“如果这里挂了怎么办”。源码部署、专用用户、定时备份、恢复演练、参数调优,做起来都不难,难的是在第一次部署时就愿意把这些“慢功夫”做足。如果按这篇文章从头到尾操作一遍,你得到的不仅是一套能跑的Odoo,更是一套知道自己每块零件在哪儿的系统,这个踏实感是任何一键脚本都给不了的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 2:29:18

期货量化策略部署全流程:从回测到实盘的关键步骤

期货量化策略部署上线全流程_从回测到实盘的关键步骤这两年做期货量化的人越来越多,但真正能把自己策略从回测搬到实盘的,比例其实低得吓人。我见过太多人卡在某个环节,有的是回测做得天衣无缝、一上模拟盘就变形,有的是参数明明在…

作者头像 李华
网站建设 2026/9/11 2:28:30

C语言数据类型深度解析与实战技巧

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 2:28:23

滑块验证的拖动逻辑:isTrusted事件如何在无鼠标环境完成拖拽

滑块验证的拖动逻辑:isTrusted事件如何在无鼠标环境完成拖拽 滑块验证的技术核心就一个动作:拖。按住、移动、松开。 人工拖:物理鼠标按下,移动到缺口,松开。物理轨迹暴露给风控分析。 脚本模拟拖:模拟鼠…

作者头像 李华
网站建设 2026/9/11 2:22:55

CodeBuddy与WorkBuddy:陈秋远揭秘大厂AI研发双引擎

当AI研发从「辅助工具」走向「开发生态」,腾讯的CodeBuddy与WorkBuddy成为两个值得解剖的样本。2026年奇点智能技术大会新增嘉宾、腾讯CodeBuddy&WorkBuddy模型研发高级研究员陈秋远将带来对这一「AI研发双引擎」的技术解读。 直接回答:CodeBuddy与…

作者头像 李华