首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Linux Oracle 資料庫啟停管理 Shell 腳本:支援多實例、參數化操作與 systemd 整合

     編輯:Oracle 資料庫基礎

生產環境常需管理多個 Oracle 實例 (SID),手動操作易出錯且難審計。本文提供一支功能完整的 **Shell 管理腳本**,支援 start|stop|restart 參數化操作、多 SID 逗號分隔批次處理、鎖機制防併發、日誌記錄、systemd 服務整合,並解析關鍵邏輯與部署細節。

腳本功能特性

  • 多實例批次:./oracled.sh start ORCL,ORCL2,ORCL3
  • 三大操作:start / stop / restart (stop→start)
  • 安全鎖機制:防止同一 SID 併發操作
  • 詳細日誌:操作時間、SID、狀態、輸出捕獲
  • 環境自適應:自動讀取 /etc/oratab 驗證 SID 合法性
  • systemd 整合:可作為服務單元管理

完整腳本 (oracled.sh)

#!/bin/bash
# oracled.sh - Oracle 實例啟停管理腳本
# 用法: ./oracled.sh [start|stop|restart] SID1,SID2,...
# 環境: 需預先配置 oracle 用戶 .bash_profile (ORACLE_HOME, PATH 等)

set -euo pipefail

SCRIPT_NAME=$(basename "$0")
LOCK_DIR="/var/lock/oracle"
LOG_DIR="/var/log/oracle"
ORATAB="/etc/oratab"

mkdir -p "$LOCK_DIR" "$LOG_DIR"

usage() {
    cat <> "$LOG_FILE"; }

exec_sqlplus() {
    local sid=$1
    local sql=$2
    local log_prefix=$3
    export ORACLE_SID="$sid"
    log_file "$log_prefix: 執行 SQL: $sql"
    sqlplus -s / as sysdba <&1 | tee -a "$LOG_FILE"
WHENEVER SQLERROR EXIT FAILURE
$sql
EXIT
EOF
    return ${PIPESTATUS[0]}
}

start_instance() {
    local sid=$1
    log_file "=== 啟動 $sid ==="
    # 1. 啟動監聽器 (僅首個 SID 執行,避免重複)
    if [[ "$sid" == "$FIRST_SID" ]]; then
        log_file "啟動監聽器..."
        lsnrctl start 2>&1 | tee -a "$LOG_FILE"
    fi
    # 2. 啟動資料庫
    exec_sqlplus "$sid" "STARTUP;" "啟動 $sid" || return 1
    log_file "=== $sid 啟動成功 ==="
}

stop_instance() {
    local sid=$1
    log_file "=== 關閉 $sid ==="
    exec_sqlplus "$sid" "SHUTDOWN IMMEDIATE;" "關閉 $sid" || return 1
    # 最後一個 SID 關閉監聽器
    if [[ "$sid" == "$LAST_SID" ]]; then
        log_file "關閉監聽器..."
        lsnrctl stop 2>&1 | tee -a "$LOG_FILE"
    fi
    log_file "=== $sid 關閉成功 ==="
}

main() {
    [[ $# -lt 1 ]] && usage
    local action=$1; shift
    [[ "$action" == "--help" || "$action" == "-h" ]] && usage

    local sids_input=${1:-}
    local sids=()

    if [[ -z "$sids_input" ]]; then
        # 從 oratab 讀取自動啟動的 SID (最後欄位為 Y)
        mapfile -t sids < <(awk -F: '$3=="Y" && $1!~/^#/ {print $1}' "$ORATAB")
        [[ ${#sids[@]} -eq 0 ]] && { log "錯誤: $ORATAB 中無自動啟動 SID"; exit 1; }
    else
        IFS=',' read -ra sids <<< "$sids_input"
    fi

    FIRST_SID=${sids[0]}
    LAST_SID=${sids[-1]}
    LOG_FILE="$LOG_DIR/oracled_${action}_$(date +%F_%H%M%S).log"

    log "開始 $action 操作,目標 SID: ${sids[*]}"
    log_file "開始 $action,SID: ${sids[*]}"

    for sid in "${sids[@]}"; do
        # 驗證 SID 存在於 oratab
        if ! grep -q "^${sid}:" "$ORATAB"; then
            log "警告: $sid 不在 $ORATAB 中,跳過"
            continue
        fi

        # 鎖檢查
        local lock_file="$LOCK_DIR/${sid}.lock"
        if [[ -f "$lock_file" ]] && kill -0 "$(cat "$lock_file" 2>/dev/null)" 2>/dev/null; then
            log "錯誤: $sid 正在被其他進程操作 (PID: $(cat "$lock_file"))"
            exit 1
        fi
        echo $$ > "$lock_file"

        case "$action" in
            start)
                start_instance "$sid" || { log "啟動 $sid 失敗"; rm -f "$lock_file"; exit 1; }
                ;;
            stop)
                stop_instance "$sid" || { log "關閉 $sid 失敗"; rm -f "$lock_file"; exit 1; }
                ;;
            restart)
                stop_instance "$sid" || { log "關閉 $sid 失敗"; rm -f "$lock_file"; exit 1; }
                sleep 3
                start_instance "$sid" || { log "啟動 $sid 失敗"; rm -f "$lock_file"; exit 1; }
                ;;
            *)
                usage
                ;;
        esac
        rm -f "$lock_file"
    done

    log "所有操作完成,日誌: $LOG_FILE"
}

main "$@"

部署與權限設置

# 1. 複製腳本
cp oracled.sh /usr/local/bin/oracled
chmod 755 /usr/local/bin/oracled
chown oracle:oinstall /usr/local/bin/oracled

# 2. 建立日誌/鎖目錄權限
mkdir -p /var/log/oracle /var/lock/oracle
chown oracle:oinstall /var/log/oracle /var/lock/oracle

# 3. 配置 /etc/oratab (由 root 或 oracle 維護)
# 格式: SID:ORACLE_HOME:Y|N
# 範例:
ORCL:/u01/app/oracle/product/19.0.0/dbhome_1:Y
ORCL2:/u01/app/oracle/product/19.0.0/dbhome_1:N

# 4. 配置 oracle 用戶 sudo 權限 (可選,systemd 需要)
# visudo 添加:
oracle ALL=(root) NOPASSWD: /bin/systemctl start oracle-*, /bin/systemctl stop oracle-*

systemd 服務整合 (每實例一服務)

# /etc/systemd/system/oracle-db@.service
[Unit]
Description=Oracle Database %i
After=network.target oracle-listener.service
Requires=oracle-listener.service

[Service]
Type=oneshot
User=oracle
Group=oinstall
Environment=ORACLE_SID=%i
ExecStart=/usr/local/bin/oracled start %i
ExecStop=/usr/local/bin/oracled stop %i
RemainAfterExit=yes
TimeoutSec=600

[Install]
WantedBy=multi-user.target

# 啟用實例服務
systemctl daemon-reload
systemctl enable oracle-db@ORCL
systemctl start oracle-db@ORCL
systemctl status oracle-db@ORCL

監聽器服務獨立管理:

# /etc/systemd/system/oracle-listener.service
[Unit]
Description=Oracle Listener
After=network.target

[Service]
Type=forking
User=oracle
Group=oinstall
Environment=ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
ExecStart=/u01/app/oracle/product/19.0.0/dbhome_1/bin/lsnrctl start
ExecStop=/u01/app/oracle/product/19.0.0/dbhome_1/bin/lsnrctl stop

[Install]
WantedBy=multi-user.target

使用範例

# 手動操作
sudo -u oracle /usr/local/bin/oracled start ORCL
sudo -u oracle /usr/local/bin/oracled stop ORCL,ORCL2
sudo -u oracle /usr/local/bin/oracled restart ORCL

# systemd 操作
systemctl start oracle-db@ORCL
systemctl stop oracle-db@ORCL
systemctl restart oracle-db@ORCL

# 查看日誌
tail -f /var/log/oracle/oracled_start_2024-01-15_143000.log
journalctl -u oracle-db@ORCL -f

關鍵設計解析

設計點實現方式效益
多 SID 批次逗號分隔 + 迴圈 + FIRST/LAST 判斷監聽器單命令管理叢集/多實例
防併發鎖/var/lock/oracle/SID.lock + PID 檢查避免同一實例並行啟停導致損壞
環境隔離迴圈內 export ORACLE_SID各實例獨立環境,互不干擾
錯誤快速失敗set -euo pipefail + sqlplus WHENEVER SQLERROR EXIT FAILURE任何步驟失敗立即中止,防止部分成功
審計日誌雙重輸出 (螢幕 + 檔案) + 時間戳滿足合規、事後追溯

擴充建議

  • 加入 status 子命令:檢查實例狀態、監聽器狀態、表空間使用率
  • 整合 RMAN 備份腳本:./oracled.sh backup ORCL
  • 支援 PFILE 指定啟動:start ORCL /custom/init.ora
  • 增加 Prometheus Exporter 推送指標:啟動耗時、狀態碼

部署此腳本並納入變更管理流程,可將 Oracle 實例啟停操作標準化、自動化、可審計,顯著降低人為誤操作風險,提升運維效率。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved