在开发测试环境中,Oracle 启动和关闭往往要分别敲 lsnrctl 和 sqlplus 命令,步骤多、容易漏,对开发人员也不友好。因为开发测试环境比较简单,启停库通常不会遇到啥异常,所以可以直接把监听器和数据库实例的启停逻辑收进一个脚本,再用两个小包装脚本分别对应启动和停止,操作起来更省心。
01 | 主脚本 db.sh 的结构
脚本放在 /home/oracle/scripts/db.sh,针对的实例是 ORCLCDB。使用前需赋予可执行权限:chmod +x /home/oracle/scripts/db.sh(包装脚本同理)。开头先明确环境变量,避免依赖登录时的默认配置:
bash
export ORACLE_SID=ORCLCDB
export ORACLE_BASE=/opt/oracle
export ORACLE_HOME=/opt/oracle/product/26ai/dbhome_1
export PATH=$ORACLE_HOME/bin:$PATH
export NLS_LANG=american_america.utf8
接着检查执行身份,只有 oracle 用户才能继续,否则直接报错退出。这样能减少用错用户的情况;但以 sqlplus / as sysdba 连接还需该用户具备相应 OS 组权限(如 dba)或已配置认证,否则仍会连接失败。
02 | 启动与停止的顺序
脚本用 case 接收参数,分三种操作。
start 时先启动监听器,再启动数据库。需要注意:脚本未检查 lsnrctl start 和 startup 的返回状态,若其中任一步失败仍会打印"启动完成",生产环境建议在关键步骤后增加返回码判断或人工确认输出:
bash
lsnrctl start
sqlplus -s / as sysdba <<EOF
startup;
exit;
EOF
stop 时顺序相反,先关数据库再停监听:
bash
sqlplus -s / as sysdba <<EOF
shutdown immediate;
exit;
EOF
lsnrctl stop
关闭用 shutdown immediate,它会回滚未提交事务并断开所有已连接会话,适合常规维护停机;对在线业务执行前应确认无关键事务进行中。启动和停止都通过 sqlplus -s / as sysdba 以静默方式执行,输出更干净。
启动与停止的操作顺序可以用下面的流程图概括:
flowchart TD A执行 db.sh --> B{参数判断} B -->|start| C启动监听器 lsnrctl start C --> D启动数据库 startup D --> E启动完成 B -->|stop| F关闭数据库 shutdown immediate F --> G停止监听器 lsnrctl stop G --> H关闭完成 B -->|status| I检查 PMON 进程 I --> J查询 v$instance 状态 J --> K查看监听器状态 B -->|其他| L提示用法并退出
03 | status 检查三项状态
status 参数用于快速体检,依次看三件事。注意:实例未启动时,查询 v$instance 会报 ORA-01034 等错误,属预期现象,可结合 PMON 进程检查判断:
- PMON 进程:
ps -ef | grep [p]mon_$ORACLE_SID - 实例状态:查询
v$instance的status字段 - 监听器状态:
lsnrctl status中过滤Status和Services Summary
三块信息拼在一起,能大致判断实例和监听是否正常。
04 | 两个包装脚本
为了少敲参数,笔者另外写了两个小脚本。start_db.sh 先定位自身所在目录,再调用主脚本的 start:
bash
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
exec "${SCRIPT_DIR}/db.sh" start
stop_db.sh 同理,只是把参数换成 stop。用 exec 替换当前进程,脚本路径通过 dirname 动态获取,因此只要 db.sh 与包装脚本位于同一目录即可调用;但 db.sh 内的 ORACLE_HOME 等路径为硬编码,迁移到其他环境时需相应修改。
如果参数不对,主脚本会提示用法:/home/oracle/scripts/db.sh {start|stop|status}。
05 | 原始完整脚本
为方便大家直接参考和取用,下面附上三个脚本的原始完整内容。只需要修改下Oracle环境变量。
db.sh
bash
#!/bin/bash
# =================================================================
# Oracle Database & Listener Control Script
# Script Path: /home/oracle/scripts/db.sh
# ORACLE_SID: ORCLCDB
# =================================================================
# 1. 明确 Oracle 环境变量(根据实际情况修改变量值)
export ORACLE_SID=ORCLCDB
export ORACLE_BASE=/opt/oracle
export ORACLE_HOME=/opt/oracle/product/26ai/dbhome_1
export PATH=$ORACLE_HOME/bin:$PATH
export NLS_LANG=american_america.utf8
# 2. 检查用户身份
if [ "$(whoami)" != "oracle" ]; then
echo "错误: 请使用 oracle 用户执行此脚本。"
exit 1
fi
# 3. 操作分发
case "$1" in
start)
echo "--------------------------------------------------"
echo "[1/2] 正在启动 Oracle 监听器..."
lsnrctl start
echo ""
echo "[2/2] 正在启动 Oracle 数据库 ($ORACLE_SID)..."
sqlplus -s / as sysdba <<EOF
startup;
exit;
EOF
echo "--> 数据库及监听启动完成。"
echo "--------------------------------------------------"
;;
stop)
echo "--------------------------------------------------"
echo "[1/2] 正在关闭 Oracle 数据库 ($ORACLE_SID)..."
sqlplus -s / as sysdba <<EOF
shutdown immediate;
exit;
EOF
echo ""
echo "[2/2] 正在停止 Oracle 监听器..."
lsnrctl stop
echo "--> 数据库及监听已安全关闭。"
echo "--------------------------------------------------"
;;
status)
echo "--------------------------------------------------"
echo "【1. PMON 进程检查】"
ps -ef | grep [p]mon_$ORACLE_SID
echo ""
echo "【2. 数据库实例状态】"
sqlplus -s / as sysdba <<EOF
set heading off
select 'Instance Status: ' || status from v\$instance;
exit;
EOF
echo ""
echo "【3. 监听器状态简报】"
lsnrctl status | grep -E "(Status|Services Summary)" -A 5
echo "--------------------------------------------------"
;;
*)
echo "用法: /home/oracle/scripts/db.sh {start|stop|status}"
exit 1
;;
esac
start_db.sh
bash
#!/bin/bash
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
exec "${SCRIPT_DIR}/db.sh" start
stop_db.sh
bash
#!/bin/bash
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
exec "${SCRIPT_DIR}/db.sh" stop
关注我,和AI一起成长~