跳轉至

建立 2026-09-20 更新 2026-09-20

odoo-bin 指令

odoo-bin 是 Odoo 的唯一入口:啟動伺服器、升級模組、進入 Python shell、備份資料庫、產生模組骨架,都是它。開發自訂模組(addon)時,你每天都會用到它。

本頁以 Odoo 18 的 --help 與實際執行結果為準。範例中的資料庫叫 mydb、模組叫 library(做法見 實作:圖書借閱模組)。

先搞懂三件事

1) 不同安裝方式,指令名稱不同

安裝方式 怎麼呼叫
原始碼(git clone) ./odoo-binpython odoo-bin
deb / rpm 套件 odoo
官方 Docker 映像 odoo(映像裡沒有 odoo-bin

本頁寫 odoo-bin,用套件或 Docker 時換成 odoo 即可,參數完全相同。Docker 的實際用法見 Docker 中怎麼用

2) 語法:子指令一定放最前面

odoo-bin [子指令] [選項...]

省略子指令就是 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 installodoo-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__.pydata 清單 需要

開發模式 --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(預設)、debugwarnerrorcriticaldebug_sqldebug_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 乾淨得多:

odoo-bin -d mydb --log-handler=odoo.addons.library: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,會連同 baseweb 等一起安裝的模組的測試都跑一遍,實測要近兩分鐘。務必用 --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)

選項太多時,寫進設定檔比較好維護:

odoo-bin -c ~/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)會把目前的選項存進設定檔,用來產生第一份設定:
odoo-bin -c ./odoo.conf -s -d mydb --addons-path=odoo/addons,addons --stop-after-init

不加 -c 的 -s 會寫進你的家目錄

只寫 -s 會覆蓋 ~/.odoorc。除非你就是要改全域設定,否則請一起指定 -c ./odoo.conf

設定檔裡的 admin_passwd

這是資料庫管理頁面的「主控密碼」(master password),預設值是 admin,用 -s 存出來的檔案也會帶著它。正式站務必改成強密碼,並考慮加 --no-database-list

scaffold:產生模組骨架

odoo-bin scaffold <模組名> [目的資料夾]
odoo-bin scaffold library ~/my_addons

會在 ~/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。內建有 defaultthemel10n_payroll

骨架裡的模型、檢視、選單全部是註解掉的範例__manifest__.py 的權限檔也被註解。你要自己解開或改寫。用不到的 controllers/views/templates.xml 可以直接刪,記得同步刪掉 __init__.py 與 manifest 裡的引用。

shell:互動式除錯

shell 開啟一個已載入 Odoo 環境的 Python 互動介面,是驗證 ORM 寫法、查資料、批次修資料最快的工具。

odoo-bin shell -d mydb --addons-path=odoo/addons,addons,../my_addons
>>> 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,你的 createwrite 全部作廢。要保留就手動呼叫 env.cr.commit()。這讓 shell 很安全,但也表示批次修資料時別忘了 commit。
  • 沒指定 -d 時沒有 env
  • 從管線(pipe)餵指令時,整段會當成一個腳本執行,運算式不會自動印出,要用 print()
echo 'print(env["library.book"].search_count([]))' | odoo-bin shell -d mydb --log-level=warn
  • 想換介面用 --shell-interface=ipython(支援 ipythonptpythonbpythonpython)。預設會依序找已安裝的。

db:資料庫管理

odoo-bin db [連線選項] <子指令> [參數]
子指令 用法 說明
dump db dump mydb mydb.zip 匯出成 zip(含 dump.sqlmanifest.jsonfilestore/ 附件)。省略檔名或寫 - 就輸出到標準輸出
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 loadduplicaterename 目標資料庫已存在時先刪掉
-n, --neutralize loadduplicate 完成後順便無害化(見 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

duplicateload 會載入資料庫的模組資訊。若沒有把自訂模組所在路徑放進 --addons-path(或用 -c 指定設定檔),日誌會出現 Some modules are not loaded, some dependencies or manifest may be missing: ['library']

備份需要 pg_dump

db dumpdb load 會呼叫 PostgreSQL 的 pg_dumppsql。它們不在 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 長這樣:

#. module: library
#: model:ir.model,name:library.model_library_book
msgid "Library Book"
msgstr ""

其他子指令

指令 用法與重點
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-runodoo/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)會把環境變數 HOSTPORTUSERPASSWORD(見 安裝與環境 的 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-enablebase 都測。改用 --test-tags /模組名

進一步學習