iT邦幫忙

2024 iThome 鐵人賽

DAY 17
0
Odoo

Odoo 部署策略系列 第 17

開發 odoo module 的小工具:快速參數調整並重啟

  • 分享至 

  • xImage
  •  

我在做官方的模組開發新手教學時,發現開發模組會常需要停掉 odoo,然後重啟並加上 -u estate 參數,來更新我們剛剛修改的模組,讓 ORM 應用我們剛剛修改的資料庫 schema;或者加上 --dev xml 讓我們在修改 XML 後只要重新整理網頁就能看到最新的變更。


問題點

然而,在我們搭建的環境中,要實現這樣的重新啟動需要:

  1. 停掉 odoo 容器。
  2. docker-composeodoo 設定中加入 CMD,值為 odoo -u estate(如果有閱讀之前關於 entrypoint.sh 的章節,應該會了解為什麼只需這樣設定就能帶入完整的 Odoo 啟動參數)。
  3. 使用 docker-compose up 重新啟動 odoo 容器。

我覺得這樣的流程實在太繁瑣,大大降低了我繼續進行新手教學的意願(沒錯我到現在還沒完成 Orz)。所以我決定尋找一個更簡便的方法來解決這個問題。


嘗試修改 entrypoint.sh

一開始,我嘗試在 entrypoint.sh 中加入類似前一章自動初始化資料庫的機制,增加以下的段落:

if [[ "$1" == "restart" ]]; then
    echo "$HEADER Stopping existing odoo process gracefully..."

    # 找到正在執行的 odoo 程序的 PID
    PIDS=$(pgrep -f "^[p]ython3 $ODOO_BIN")
    if [ -z "$PIDS" ]; then
        echo "$HEADER No running odoo process found."
        exit 1
    fi

    PID_COUNT=$(echo "$PIDS" | wc -w) # 計算找到的 PID 數量

    if [ "$PID_COUNT" -gt 1 ]; then
        echo "$HEADER Multiple odoo processes found (PIDs: $PIDS). Aborting to prevent accidental termination."
        exit 1
    fi

    PID=$PIDS
    echo "$HEADER Found odoo process with PID: $PID"

    kill $PID # 發送 SIGTERM 信號,進行 Graceful Shutdown

    # 等待 Graceful Shutdown
    echo "$HEADER Waiting for odoo process to stop..."
    TIMEOUT=30  # 超時時間(秒)
    ELAPSED=0
    while kill -0 $PID 2>/dev/null; do
        if [ $ELAPSED -ge $TIMEOUT ]; then
            echo "$HEADER Failed to stop odoo process $PID within timeout."
            exit 1
        fi
        sleep 1
        ELAPSED=$((ELAPSED + 1))
    done

    echo "$HEADER odoo process $PID has been stopped."

    shift # 移除 'restart' 參數

    echo "$HEADER Starting odoo with new parameters."
    echo "$HEADER Executing: $ODOO_BIN $@ ${DB_ARGS[@]}"
    exec $ODOO_BIN "$@" "${DB_ARGS[@]}"
fi

這樣我就能在 Odoo 容器運行的狀態下,透過在 host 執行 docker-compose exec odoo /entrypoint.sh odoo restart -u estate,使用同一個 entrypoint.sh 來達成目的。

然而,經過一番嘗試後,我發現我忽略了一個 Docker 的重要特性——只要 PID 1(也就是容器內的第一個程序)停止,整個容器就會關閉,這個腳本的後半部分也無法執行。如果要解決這個問題,就必須大幅修改 Docker 的執行方式,讓容器內有其他常駐的程序作為 PID 1,並透過它來管理 odoo 的運行。

考慮到這樣的修改實在過於繁瑣,我最終放棄了這個方案。


方案二:使用 Bash 腳本與 docker-compose.override.yml

第二個解決方案是撰寫一個小腳本——odoo-restart.sh,從 host 執行這個腳本來解決問題。

# 顯示使用說明的 Function
usage() {
    echo "Usage: $0 [odoo command parameters]"
    echo "Example:"
    echo "  $0"
    echo "  $0 -u estate"
    echo "  $0 -u estate --dev xml"
    exit 1
}

# 檢查是否請求顯示幫助內容
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
    usage  # 如果提供了 -h 或 --help 參數,則顯示使用說明
fi

# 第一步:停止 odoo 容器
echo "Stopping odoo container..."
docker-compose stop odoo  # 停止 odoo 容器
if [ $? -ne 0 ]; then  # 檢查停止是否成功
    echo "Error: Failed to stop odoo container."  # 如果停止失敗,顯示錯誤
    exit 1
fi

# 第二步:根據參數生成 docker-compose.override.yml 文件
# 如果提供了參數,將其作為 odoo 的啟動指令
if [ "$#" -gt 0 ]; then
    echo "Creating docker-compose.override.yml with the following command: odoo $@"  # 顯示將要創建的指令
    CMD="odoo $@"
else
    echo "Creating docker-compose.override.yml with the default command: odoo"  # 如果沒有提供參數,使用預設的 odoo 指令
    CMD="odoo"
fi

# 將生成的指令寫入 docker-compose.override.yml 檔案
cat > docker-compose.override.yml <<EOF
services:
  odoo:
    command: $CMD
EOF
# EOF 是這段檔案的結尾標記,用於標識多行輸入的結束

# 第三步:使用新的設定啟動 odoo 容器
echo "Starting odoo container with updated command..."
docker-compose up -d odoo  # 使用更新的指令啟動 odoo 容器
if [ $? -ne 0 ]; then  # 檢查啟動是否成功
    echo "Error: Failed to start odoo container."  # 如果啟動失敗,顯示錯誤
    # 在退出前刪除 docker-compose.override.yml 文件
    rm -f docker-compose.override.yml
    exit 1
fi

echo "Waiting for odoo to initialize..."
sleep 10  # 等待 10 秒以讓 odoo 完成初始化

# 第四步:移除 docker-compose.override.yml 檔案
echo "Removing docker-compose.override.yml..."
rm -f docker-compose.override.yml  # 移除臨時的 override 檔案

echo "odoo has been restarted with the specified parameters."  # 完成並顯示成功訊息

關於 docker-compose.override.yml:

docker-compose.override.yml 是 Docker Compose 提供的一種機制,允許在不修改原始 docker-compose.yml 的情況下,臨時覆蓋或添加配置。這對於開發環境特別有用,我們可以根據需要動態調整設定,而不影響版本控制中的原始設定。

最終這個小腳本的測試結果符合預期。開發時如果需要重啟並加參數,只需執行類似 ./odoo-restart.sh -u estate 的指令,就能簡單有效地達成目的。


上一篇
odoo 建立一步到位:自動化資料庫初始流程
下一篇
整合 pgAdmin 容器:提升 odoo 開發除錯體驗
系列文
Odoo 部署策略30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言