odoo-bin 指令
odoo-bin 是 Odoo 的唯一入口:啟動伺服器、升級模組、進入 Python shell、備份資料庫、產生模組骨架,都是它。開發自訂模組(addon)時,你每天都會用到它。
本頁以 Odoo 18 的 --help 與實際執行結果為準。範例中的資料庫叫 mydb、模組叫 library(做法見 實作:圖書借閱模組)。
先搞懂三件事
1) 不同安裝方式,指令名稱不同
| 安裝方式 | 怎麼呼叫 |
|---|---|
| 原始碼(git clone) | ./odoo-bin 或 python odoo-bin |
| deb / rpm 套件 | odoo |
| 官方 Docker 映像 | odoo(映像裡沒有 odoo-bin) |
本頁寫 odoo-bin,用套件或 Docker 時換成 odoo 即可,參數完全相同。Docker 的實際用法見 Docker 中怎麼用。
2) 語法:子指令一定放最前面
省略子指令就是 server(啟動伺服器)。子指令必須是第一個參數,若前面先放了選項,Odoo 會把整行當成 server 的選項,於是報錯:
odoo-bin --db_host=localhost shell -d mydb
# odoo-bin server: error: unrecognized parameters: 'shell'
odoo-bin shell -d mydb --db_host=localhost # 正確
唯一例外是 --addons-path=... 可以放在子指令前面(讓 Odoo 找得到藏在自訂模組裡的子指令)。
3) 每個子指令有自己的 --help
odoo-bin help # 列出所有子指令
odoo-bin --help # server 的完整選項
odoo-bin shell --help # 其他子指令的選項
odoo-bin --version # Odoo Server 18.0
子指令一覽
| 子指令 | 用途 | 你會多常用 |
|---|---|---|
server(預設) |
啟動伺服器,或搭配 -i、-u 安裝/升級模組 |
每天 |
scaffold |
產生模組骨架 | 建立新模組時 |
shell |
開啟載入 Odoo 環境的 Python 互動介面 | 每天(除錯、批次修資料) |
db |
備份、還原、複製、改名、刪除資料庫 | 常用 |
cloc |
統計自訂程式碼行數 | 偶爾 |
neutralize |
讓正式資料庫的副本「無害化」(不寄信等) | 拿正式資料測試時 |
populate |
複製既有資料,產生大量測試資料 | 效能測試 |
upgrade_code |
依腳本批次改寫原始碼,適配新版 Odoo | 換大版時 |
start |
用預設值快速啟動(自動建庫、加 --db-filter) |
快速試做 |
deploy |
把模組上傳到遠端執行中的 Odoo | 少用 |
genproxytoken |
產生代理存取權杖並寫入設定檔 | 少用 |
tsconfig |
為 JavaScript 產生 tsconfig(給編輯器用) |
前端開發 |
obfuscate |
對資料庫內容做混淆 | 少用 |
Odoo 18 沒有 module、i18n 子指令
網路上的教學若出現 odoo-bin module install 或 odoo-bin i18n export,那是 Odoo 19 之後的寫法。Odoo 18 的安裝、升級與翻譯,都是 server 的選項(-i、-u、--i18n-export),見下文。
server:啟動與升級
最常用的六種組合
# 1. 啟動伺服器,連到 mydb
odoo-bin -d mydb --addons-path=odoo/addons,addons,../my_addons
# 2. 安裝模組(新資料庫也用這招建立)
odoo-bin -d mydb -i library --stop-after-init
# 3. 升級模組(改了 Python 欄位、XML、CSV 之後)
odoo-bin -d mydb -u library --stop-after-init
# 4. 開發模式:改 Python 自動重啟、改檢視不用升級
odoo-bin -d mydb --dev=all
# 5. 跑測試(只跑自己的模組)
odoo-bin -d mydb -u library --test-tags /library --stop-after-init
# 6. 換個埠,避免與已經在跑的 Odoo 衝突
odoo-bin -d mydb -p 8070
以下逐組說明選項。
資料庫
| 選項 | 說明 |
|---|---|
-d, --database |
資料庫名稱。可用逗號指定多個,但搭配 -i/-u 時只能一個 |
-r, --db_user |
資料庫使用者 |
-w, --db_password |
資料庫密碼 |
--db_host, --db_port |
PostgreSQL 位址與埠(預設走本機 Unix socket) |
--db-filter |
用正規表示式限定網頁可見的資料庫,例如 ^mydb$(多站台部署很重要) |
--no-database-list |
隱藏資料庫選擇與管理頁面。上線時建議搭配 -d 使用 |
--db_maxconn |
連線池上限,預設 64 |
不可用 postgres 超級使用者
用 postgres 連線時,Odoo 會直接拒絕:Using the database user 'postgres' is a security risk, aborting. 請另建一個有 CREATEDB 權限的角色(Docker 映像預設就是 odoo)。
-i 與 -u:安裝與升級
| 選項 | 行為 |
|---|---|
-i a,b |
安裝模組(逗號分隔),需搭配 -d |
-u a,b |
升級模組。-u all 升級所有已安裝的模組 |
--stop-after-init |
初始化完就結束,不啟動 HTTP 服務 |
--without-demo=all |
安裝時不載入示範資料。正式站請務必加 |
--skip-auto-install |
不自動安裝 auto_install 模組 |
幾個實測確認過的行為:
- 每次
-i/-u都會先更新模組清單(日誌可看到updating modules list)。所以剛建立的新模組,直接-i 模組名就找得到,不需要先到網頁按「更新應用程式清單」。 - 模組名稱打錯不會報錯,只會警告後忽略:
invalid module names, ignored: nosuchmod。安裝沒反應時先看日誌有沒有這一行。 -u會連帶升級依賴它的已安裝模組。升級sale時,依賴sale的模組也會一起升級。- 只想看結果、不要伺服器一直跑著,就加
--stop-after-init。它也不會開 HTTP 埠,所以不會與正在運行的 Odoo 搶 8069。
什麼時候需要 -u:
| 你改了什麼 | 需要 -u? |
|---|---|
模型欄位、_name、_inherit |
需要(資料庫結構要更新) |
| XML 檢視、選單、資料檔、CSV 權限 | 需要(除非用 --dev=xml,僅限檢視) |
| 只改方法內的 Python 邏輯 | 不需要,重啟即可(--dev=reload 會自動重啟) |
__manifest__.py 的 data 清單 |
需要 |
開發模式 --dev
--dev=all 等於 --dev=reload,qweb,xml。可以只開其中幾項,用逗號分隔:
| 值 | 效果 |
|---|---|
reload |
偵測到 Python 檔案變動,自動重啟伺服器。需要 watchdog(macOS/Windows)或 inotify(Linux)套件,沒裝時啟動會有警告 |
xml |
檢視內容直接從檔案讀取,改完 XML 重新整理網頁就生效,不必 -u |
qweb |
QWeb 模板除錯(可在模板節點加 t-debug 中斷偵錯) |
正常時,啟動日誌會出現 AutoReload watcher running with watchdog。
與網頁的開發者模式是兩回事
--dev 是伺服器啟動選項。瀏覽器網址加 ?debug=1(或在設定頁啟用開發者模式)是前端的偵錯工具(顯示欄位技術名稱、編輯檢視等)。開發時兩個通常一起開。
模組路徑與資料目錄
| 選項 | 說明 |
|---|---|
--addons-path |
模組搜尋目錄,逗號分隔。放自訂模組的上一層目錄,不是模組本身 |
-D, --data-dir |
資料目錄(filestore 附件、session 存放處) |
--load |
伺服器層級的模組,預設 base,web |
--addons-path 常見錯誤是指到模組資料夾本身。例如模組在 ~/my_addons/library/,應寫 --addons-path=...,~/my_addons。
HTTP 與代理
| 選項 | 預設 | 說明 |
|---|---|---|
-p, --http-port |
8069 | 網頁服務埠 |
--http-interface |
空(所有介面) | 監聽位址。只給本機用可設 127.0.0.1 |
--gevent-port |
8072 | 即時通訊(longpolling)埠,多程序模式才用 |
--proxy-mode |
關 | 放在 Nginx 等反向代理後面時開,讓 Odoo 信任轉發標頭。沒有代理時不要開 |
--no-http |
不開 HTTP(只跑排程等) |
驗活可以用 GET /web/health,正常回傳 {"status": "pass"},適合放在 Docker healthcheck。
日誌
| 選項 | 說明 |
|---|---|
--log-level= |
info(預設)、debug、warn、error、critical、debug_sql、debug_rpc 等 |
--log-sql |
等同 --log-handler=odoo.sql_db:DEBUG,印出所有 SQL |
--log-web |
等同 --log-handler=odoo.http:DEBUG |
--log-handler=前綴:等級 |
針對單一 logger 調整,可重複,例如 odoo.addons.library:DEBUG |
--logfile= |
寫入檔案(預設印到終端機) |
只看自己模組的 debug 訊息,比整個 --log-level=debug 乾淨得多:
測試
| 選項 | 說明 |
|---|---|
--test-enable |
啟用單元測試 |
-t, --test-tags |
用標籤篩選測試;有指定時等於自動啟用測試 |
--test-file |
執行單一 Python 測試檔 |
--test-tags 格式:[-][標籤][/模組][:類別][.方法],- 表示排除。
--test-tags /library # library 模組的所有測試
--test-tags /library:TestLoan # 只跑 TestLoan 類別
--test-tags /library:TestLoan.test_due_date # 只跑單一方法
--test-tags /library,-/library:TestSlow # 排除某個類別
全新資料庫別直接加 --test-enable
在全新資料庫執行 -i library --test-enable,會連同 base、web 等一起安裝的模組的測試都跑一遍,實測要近兩分鐘。務必用 --test-tags /library 限定範圍。
多程序與資源限制(正式環境)
預設是單程序多執行緒(--workers=0),適合開發。正式站通常開多程序:
| 選項 | 預設 | 說明 |
|---|---|---|
--workers |
0 | 工作程序數,0 表示不啟用。常見做法是 CPU 核心數 × 2 起算再調整 |
--max-cron-threads |
2 | 同時處理排程的執行緒數 |
--limit-memory-soft |
2048 MiB | 單一 worker 記憶體軟上限,超過後處理完當前請求就重啟 |
--limit-memory-hard |
2560 MiB | 硬上限,超過就無法配置記憶體 |
--limit-time-cpu |
60 秒 | 單一請求 CPU 時間上限 |
--limit-time-real |
120 秒 | 單一請求實際時間上限 |
--limit-request |
65536 | 單一 worker 處理多少請求後重啟 |
開啟 --workers 後,即時通訊改走 --gevent-port,代理要另外轉發,見 Docker 部署。
寄信與其他
| 選項 | 說明 |
|---|---|
--smtp、--smtp-port、--smtp-user、--smtp-password、--smtp-ssl |
外寄郵件伺服器,見 郵件設定 |
--email-from |
預設寄件者 |
--unaccent |
建立資料庫時啟用 unaccent(搜尋忽略重音符號) |
--pidfile |
把程序 ID 寫入檔案 |
設定檔(odoo.conf)
選項太多時,寫進設定檔比較好維護:
[options]
addons_path = /opt/odoo/addons,/opt/my_addons
db_host = localhost
db_user = odoo
db_password = change_me
http_port = 8069
規則:
- 鍵名 = 選項名,連字號換底線:
--http-port寫成http_port,--db_host就是db_host。 - 命令列優先於設定檔。
- 沒指定
-c時,Odoo 讀~/.odoorc(也可用環境變數ODOO_RC指定)。 - 加
-s(--save)會把目前的選項存進設定檔,用來產生第一份設定:
不加 -c 的 -s 會寫進你的家目錄
只寫 -s 會覆蓋 ~/.odoorc。除非你就是要改全域設定,否則請一起指定 -c ./odoo.conf。
設定檔裡的 admin_passwd
這是資料庫管理頁面的「主控密碼」(master password),預設值是 admin,用 -s 存出來的檔案也會帶著它。正式站務必改成強密碼,並考慮加 --no-database-list。
scaffold:產生模組骨架
會在 ~/my_addons/library/ 產生:
library/
├─ __init__.py
├─ __manifest__.py
├─ controllers/
│ ├─ __init__.py
│ └─ controllers.py
├─ demo/
│ └─ demo.xml
├─ models/
│ ├─ __init__.py
│ └─ models.py
├─ security/
│ └─ ir.model.access.csv
└─ views/
├─ templates.xml
└─ views.xml
| 參數 | 說明 |
|---|---|
name |
模組名稱(必填),用英文小寫與底線 |
dest |
目的資料夾,預設為目前目錄 . |
-t, --template |
範本名稱或範本資料夾路徑,預設 default。內建有 default、theme、l10n_payroll |
骨架裡的模型、檢視、選單全部是註解掉的範例,__manifest__.py 的權限檔也被註解。你要自己解開或改寫。用不到的 controllers/ 與 views/templates.xml 可以直接刪,記得同步刪掉 __init__.py 與 manifest 裡的引用。
shell:互動式除錯
shell 開啟一個已載入 Odoo 環境的 Python 互動介面,是驗證 ORM 寫法、查資料、批次修資料最快的工具。
>>> books = env["library.book"].search([])
>>> books.mapped("name")
['Odoo 開發入門', 'Python 學習手冊']
>>> env["library.loan"].search([("state", "=", "borrowed")]).read(["name", "date_due"])
預先定義好的變數:
| 變數 | 內容 |
|---|---|
env |
Odoo 環境(Environment),用它取得任何模型 |
self |
目前使用者記錄(env.user) |
odoo |
odoo 套件本身(例如 odoo.release.version) |
重點行為(都已實測):
- 預設不會存檔。離開 shell 時會 rollback,你的
create/write全部作廢。要保留就手動呼叫env.cr.commit()。這讓 shell 很安全,但也表示批次修資料時別忘了 commit。 - 沒指定
-d時沒有env。 - 從管線(pipe)餵指令時,整段會當成一個腳本執行,運算式不會自動印出,要用
print():
- 想換介面用
--shell-interface=ipython(支援ipython、ptpython、bpython、python)。預設會依序找已安裝的。
db:資料庫管理
| 子指令 | 用法 | 說明 |
|---|---|---|
dump |
db dump mydb mydb.zip |
匯出成 zip(含 dump.sql、manifest.json、filestore/ 附件)。省略檔名或寫 - 就輸出到標準輸出 |
load |
db load newdb mydb.zip |
從 zip 還原。省略資料庫名稱時,用檔名(去掉副檔名) |
duplicate |
db duplicate mydb mydb_test |
複製資料庫(含附件) |
rename |
db rename mydb mydb_old |
改名(含附件) |
drop |
db drop mydb_test |
刪除資料庫(含附件),沒有二次確認 |
選項:
| 選項 | 適用 | 說明 |
|---|---|---|
-f, --force |
load、duplicate、rename |
目標資料庫已存在時先刪掉 |
-n, --neutralize |
load、duplicate |
完成後順便無害化(見 neutralize) |
--move |
load |
以「搬移」方式還原,保留資料庫 UUID(預設會產生新的) |
連線選項(-c、-D、--addons-path、-r、-w、--db_host、--db_port、--pg_path、--db_sslmode)必須放在子指令之前:
odoo-bin db --db_host=localhost -r odoo -w odoo dump mydb mydb.zip # 正確
odoo-bin db dump mydb mydb.zip --db_host=localhost # 錯誤:unrecognized arguments
常見情境:
# 拿正式資料做測試:複製 + 無害化(不會對真實客戶寄信)
odoo-bin db duplicate -n mydb mydb_test
# 每日備份
odoo-bin db dump mydb backup_$(date +%F).zip
# 還原到新機器
odoo-bin db load -f mydb backup_2026-09-20.zip
含自訂模組的資料庫,請帶 --addons-path
duplicate、load 會載入資料庫的模組資訊。若沒有把自訂模組所在路徑放進 --addons-path(或用 -c 指定設定檔),日誌會出現 Some modules are not loaded, some dependencies or manifest may be missing: ['library']。
備份需要 pg_dump
db dump 與 db load 會呼叫 PostgreSQL 的 pg_dump、psql。它們不在 PATH 時,用 --pg_path= 指定所在目錄。
翻譯匯出與匯入
Odoo 18 的翻譯是 server 的選項,需要 -d:
# 匯出翻譯範本(.pot,不含語言)
odoo-bin -d mydb --modules=library --i18n-export=library.pot --stop-after-init
# 載入繁體中文,然後匯出該語言的 .po 給翻譯人員填
odoo-bin -d mydb --load-language=zh_TW -u library --stop-after-init
odoo-bin -d mydb --modules=library -l zh_TW --i18n-export=zh_TW.po --stop-after-init
# 匯入翻好的 .po
odoo-bin -d mydb -l zh_TW --i18n-import=zh_TW.po --i18n-overwrite --stop-after-init
| 選項 | 說明 |
|---|---|
--modules |
要匯出的模組,逗號分隔 |
-l, --language |
語言代碼(如 zh_TW),匯出與匯入 .po 時必要 |
--i18n-export= |
匯出檔名,副檔名決定格式(.pot/.po/.csv/.tgz) |
--i18n-import= |
匯入 .csv 或 .po,必須搭配 -l |
--i18n-overwrite |
覆蓋已有的翻譯 |
--load-language= |
為資料庫載入語言 |
官方慣例是程式碼裡寫英文原文,再放 i18n/zh_TW.po 翻譯,升級模組時自動載入。匯出的 .pot 長這樣:
其他子指令
| 指令 | 用法與重點 |
|---|---|
cloc |
odoo-bin cloc -d mydb 統計資料庫中自訂模組的程式碼行數;odoo-bin cloc --path ./library -v 統計指定路徑,-v 顯示每個檔案。統計 Python、JavaScript、XML,Odoo 官方用它衡量客製規模 |
neutralize |
odoo-bin neutralize -d mydb 讓資料庫「無害化」:停用外寄郵件、排程、支付與外部整合。加 --stdout 只印出將執行的 SQL,不真的改。只能對複本使用 |
populate |
odoo-bin populate -d mydb --models res.partner,library.book --factors 3 複製既有記錄產生測試資料。--factors 是倍數(可為每個模型指定,以逗號分隔),--models 指定模型,--sep 指定文字欄位分隔字元 |
upgrade_code |
odoo-bin upgrade_code --from 17.0 --dry-run 依 odoo/upgrade_code/ 底下的腳本批次改寫程式(例如把 <tree> 改成 <list>)。先用 --dry-run 列出會動到的檔案。選項有 --script、--from、--to、--glob、--addons-path |
start |
odoo-bin start 快速啟動:以目前資料夾名稱建庫並安裝 base、限定 --db-filter。選項 --path、-d。適合臨時試做,不適合正式使用 |
deploy |
odoo-bin deploy ./library http://localhost:8069 --db mydb --login admin --password admin 把模組壓成 zip 上傳到執行中的 Odoo(需該站已安裝 base_import_module)。--force 會重新初始化並更新 noupdate 記錄 |
genproxytoken |
odoo-bin genproxytoken -c odoo.conf 產生並寫入代理存取權杖,--token-length 指定長度 |
tsconfig |
odoo-bin tsconfig --addons-path=... 產生 JavaScript 的 tsconfig.json,讓編輯器能補全 |
Docker 中怎麼用
官方映像的入口程式(entrypoint)會把環境變數 HOST、PORT、USER、PASSWORD(見 安裝與環境 的 Compose)轉成資料庫連線參數,再呼叫 odoo。所以用 docker compose run 最省事:
# 建立模組骨架(檔案會出現在掛載的 ./addons)
docker compose run --rm odoo odoo scaffold library /mnt/extra-addons
# 安裝、升級、跑測試(用一個一次性容器,跑完就消失)
docker compose run --rm odoo odoo -d mydb -i library --stop-after-init
docker compose run --rm odoo odoo -d mydb -u library --stop-after-init
docker compose run --rm odoo odoo -d mydb -u library --test-tags /library --stop-after-init
# 互動式 shell
docker compose run --rm odoo odoo shell -d mydb
注意:
docker compose exec odoo odoo ...(進入執行中的容器)不會經過 entrypoint,沒有自動帶資料庫連線參數,要自己加:--db_host=db -r odoo -w odoo。- 容器內建立的檔案,在主機上的擁有者可能不是你,編輯前先
sudo chown -R $USER addons/library。 - 想讓伺服器本身帶
--dev=all,可在 Compose 的odoo服務加上command: odoo --dev=all,並確認映像有watchdog套件,否則會看到 autoreload 停用的警告。
常見錯誤速查
| 訊息或現象 | 原因與處理 |
|---|---|
unrecognized parameters: 'shell' |
子指令前面放了選項。把子指令移到第一個參數 |
Using the database user 'postgres' is a security risk, aborting. |
不能用 postgres。改用有 CREATEDB 的普通角色 |
invalid module names, ignored: xxx |
模組名稱打錯,或 --addons-path 沒包含它所在的目錄 |
Some modules are not loaded ... ['library'] |
資料庫有這個模組,但這次啟動找不到它。補上 --addons-path |
-u 之後畫面沒變 |
沒硬性重新整理瀏覽器(快取),或改的是 Python 但伺服器沒重啟 |
加了 -i、-u 卻直接開始服務 |
沒加 --stop-after-init,它會升級完接著繼續跑,這不是錯誤 |
| 埠 8069 被占用 | 已有另一個 Odoo 在跑。換埠 -p 8070,或先停掉舊的 |
-i 全新資料庫測試超級久 |
--test-enable 連 base 都測。改用 --test-tags /模組名 |
進一步學習
- Odoo 18 命令列介面(官方參考)
- Odoo 原始碼:odoo/cli(每個子指令都是一個很短的 Python 檔,最準確的說明書)
- 本站:開發入門、實作:圖書借閱模組、Docker 部署