🔥 前言:做开发、测试或服务器运维的同学,是不是每天上班第一件事就是登录Linux服务器、启动Oracle数据库?关机时还要手动关闭数据库,生怕强制关机导致数据损坏、日志丢失!重复操作浪费时间,还容易遗漏步骤!今天分享核心技巧,实现Linux下Oracle开机自启动、关机自关闭,还能自动发送邮件通知状态,设置一次,长期生效,彻底解放双手,提升摸鱼(划掉)工作效率!
💡 适用场景:Oracle数据库运维、Linux服务器值守、开发/测试环境部署,支持CentOS 7/8、RHEL 7/8所有版本,兼容Oracle 11g/12c/19c主流版本,新手也能一步到位,全程复制命令即可完成!
一、先搞懂前提:环境准备(必做,避免后续踩坑)
操作前先确认2个核心前提,缺一不可,否则会导致自启/自关失败,新手必看!
-
确认Oracle环境正常:登录Linux服务器,切换到oracle用户(su - oracle),输入sqlplus / as sysdba,执行startup,能正常启动数据库;执行shutdown immediate,能正常关闭数据库,说明Oracle环境无问题。
-
确认邮件服务可用:本文采用Linux自带sendmail服务发送通知邮件,需提前安装并启动(后续会分步讲解,无需提前操作,跟着步骤来即可),支持发送到QQ邮箱、企业邮箱。
注意:本文所有操作均以「root用户」执行(除Oracle相关命令),Oracle安装路径默认「/opt/oracle/product/11.2.0/dbhome_1」,若你的安装路径不同,替换所有命令中的路径即可。
二、核心操作:Oracle开机自启动
开机自启动是基础,分「rc.local脚本(简单易操作,新手推荐)」和「systemd服务(稳定可靠,运维首选)」,根据自己的Linux版本选择,CentOS 7+优先方法2,CentOS 6优先方法1。
方法:rc.local脚本自启(简单直接,新手友好)
适用:CentOS 6/7/8通用,无需复杂配置,编辑脚本、添加权限即可,适合新手快速上手。
-
编辑rc.local文件:执行命令(直接复制),打开自启配置文件: vi /etc/rc.d/rc.local
-
添加自启脚本:在文件末尾添加以下内容(替换Oracle安装路径和用户名,默认无需修改):
bash# 注意 start_oracle_mail.sh 脚本中的内容,如果是用root账户执行的 su - oracle -c "lsnrctl start" 则无需在rc.local中切换账号 /bin/bash /home/oracle/start_oracle_mail.sh # 如果是oracle账户执行的命令,即 start_oracle_mail.sh 脚本中命令:lsnrctl start ,则在 rc.local 前需要加入账号切换 su - oracle -lc "/bin/bash /home/oracle/start_oracle_mail.sh" -
添加执行权限:执行以下命令,确保rc.local文件可执行(否则自启失效): chmod +x /etc/rc.d/rc.local
-
startup_oracle_mail.sh 脚本内容如下:
bash#!/bin/bash ########################################################### # Oracle 自动启动脚本 # 顺序:先启动监听 → 再启动数据库实例 # 功能:判断是否已运行,未运行才启动 + 邮件通知 ########################################################### # ====================== 请修改这里的配置 ====================== ORACLE_HOME=/opt/oracle/product/11.2.0/dbhome_1 ORACLE_SID=ORCL LOG_FILE=/home/oracle/oracle_start_log/`date "+%Y%m%d-%H%M%S"`_log_z.txt ## 日志存放地址 # ============================================================ # 确保日志目录存在 mkdir -p /home/oracle/oracle_start_log export ORACLE_HOME export ORACLE_SID export PATH=$ORACLE_HOME/bin:$PATH # 日志开头 echo "=============================================" >> $LOG_FILE echo "检查时间:$(date +'%Y-%m-%d %H:%M:%S')" >> $LOG_FILE # 记录最终消息 MSG="" ########################################################################### # 第一步:检查并启动监听(先启动监听) ########################################################################### LSNR_STATUS=$(ps -ef | grep tnslsnr | grep -v grep | wc -l) if [ $LSNR_STATUS -eq 0 ]; then echo "监听未运行 → 开始启动监听" >> $LOG_FILE su - oracle -c "lsnrctl start" >> $LOG_FILE 2>&1 # 监听启动后短暂等待 sleep 2 LSNR_AFTER=$(ps -ef | grep tnslsnr | grep -v grep | wc -l) if [ $LSNR_AFTER -ge 1 ]; then MSG+="✅ 监听已成功启动\n" else MSG+="❌ 监听启动失败\n" fi else MSG+="ℹ️ 监听已在运行,无需启动\n" fi ########################################################################### # 第二步:检查并启动数据库实例(后启动实例) ########################################################################### # 优化:用oracle自带工具检查实例状态(比ps更可靠) check_db_status() { su - oracle -c "sqlplus -s / as sysdba << EOF set heading off; set feedback off; select 'RUNNING' from dual where instance_status = 'OPEN'; exit; EOF" | grep -i "RUNNING" > /dev/null 2>&1 return $? } # 先执行基础进程检查 DB_STATUS=$(ps -ef | grep "ora_pmon_$ORACLE_SID" | grep -v grep | wc -l) if [ $DB_STATUS -eq 0 ]; then echo "实例未运行 → 开始启动实例" >> $LOG_FILE su - oracle -c "sqlplus / as sysdba << EOF startup; exit; EOF" >> $LOG_FILE 2>&1 # 关键优化:实例启动后等待5秒(让进程完全生成) sleep 5 # 双重验证:先查进程 → 再用sqlplus查实例状态 DB_AFTER=$(ps -ef | grep "ora_pmon_$ORACLE_SID" | grep -v grep | wc -l) if [ $DB_AFTER -ge 1 ] || check_db_status; then MSG+="✅ Oracle 实例已成功启动\n" MSG+="oracle well startup\n" else MSG+="❌ Oracle 实例启动失败\n" fi else MSG+="ℹ️ Oracle 实例已在运行,无需启动\n" MSG+="oracle well startup\n" fi # 记录日志 echo -e "$MSG" >> $LOG_FILE echo "=============================================" >> $LOG_FILE echo "" >> $LOG_FILE # 发送邮件通知 MAIL_TO="你的邮箱地址" SMTP_USER="你的邮箱地址" SMTP_PASS="你的邮箱授权码,需要申请" SMTP_SERVER="smtp.163.com" NOW_TIME=$(date +"%Y-%m-%d %H:%M:%S") SUBJECT="Oracle Server Startup Success" # ========== 正确拼接邮件内容 ========== CONTENT="Server startup Time: $NOW_TIME DB: ORCL Status: Oracle Safe Startup Finish $MSG" # 发送邮件 echo -e "\n[2/3] Sending mail..." # 修复:Python Here Document 结束标记EOF单独一行,无空格 python - << EOF # -*- coding: utf-8 -*- import smtplib from email.mime.text import MIMEText msg = MIMEText('''$CONTENT''','plain','utf-8') msg['From'] = '$SMTP_USER' msg['To'] = '$MAIL_TO' msg['Subject'] = '$SUBJECT' try: server = smtplib.SMTP('$SMTP_SERVER', 25) server.login('$SMTP_USER', '$SMTP_PASS') server.sendmail('$SMTP_USER', ['$MAIL_TO'], msg.as_string()) server.quit() print("Mail send OK") except Exception as e: print("Mail send FAIL") print(str(e)) # 打印具体错误,方便排查 EOF echo -e "\n[3/3] Script finished"
三、关键步骤:Oracle关机自关闭
服务器关机时,必须先关闭Oracle数据库和监听,否则会导致数据损坏、日志错乱!以下方案和上面的开机自启方法对应,按需选择,步骤可直接复制。
方案:rc.local脚本对应------关机自关闭(简单直接)
-
创建关机脚本:执行命令,创建关机脚本文件: vi /home/oracle/shutdown_oracle_mail.sh
-
添加脚本内容:
bash#!/bin/bash export ORACLE_SID=ORCL export ORACLE_HOME=/opt/oracle/product/11.2.0/dbhome_1 export PATH=$ORACLE_HOME/bin:$PATH MAIL_TO="你的邮箱地址" SMTP_USER="你的邮箱地址" SMTP_PASS="你的邮箱授权码,需要申请" SMTP_SERVER="smtp.163.com" NOW_TIME=$(date +"%Y-%m-%d %H:%M:%S") SUBJECT="Oracle Server Will Shutdown" CONTENT="Server Shutdown Time: $NOW_TIME DB: ORCL Status: Oracle Safe Shutdown Finish" echo "=============================================" echo "Oracle Safe Shutdown + Mail" echo "=============================================" # 检查 Oracle 是否运行(通用版,不写死 ORCL) echo -e "\n[1/3] Check Oracle status..." ps -ef | grep ora_pmon | grep -v grep >/dev/null if [ $? -eq 0 ];then echo "Oracle is running, stopping..." su - oracle -c " sqlplus / as sysdba << EOF shutdown immediate; exit; EOF " # 等待完全关闭 while true; do ps -ef | grep ora_pmon | grep -v grep >/dev/null if [ $? -ne 0 ];then echo "Oracle stopped successfully" break fi sleep 2 done else echo "Oracle is already stopped" fi # 发送邮件 echo -e "\n[2/3] Sending mail..." python - << EOF # -*- coding: utf-8 -*- import smtplib from email.mime.text import MIMEText msg = MIMEText('''$CONTENT''','plain','utf-8') msg['From'] = '$SMTP_USER' msg['To'] = '$MAIL_TO' msg['Subject'] = '$SUBJECT' try: server = smtplib.SMTP('$SMTP_SERVER', 25) server.login('$SMTP_USER', '$SMTP_PASS') server.sendmail('$SMTP_USER', ['$MAIL_TO'], msg.as_string()) server.quit() print("Mail send OK") except Exception as e: print("Mail send FAIL") EOF # 关机 echo -e "\n[3/3] System shutdown after 3 seconds..." sleep 3 shutdown -h now -
添加执行权限:执行命令,赋予脚本可执行权限: chmod +x /etc/init.d/shutdown_oracle_mail.sh
-
配置关机触发:通过定时任务关机,比如每天晚上22点关机,先关闭oracle,后半闭虚拟机:
bashcrontab -e 0 22 * * * /root/shutdown_mail.sh >/dev/null 2>&1
四、避坑指南:90%的人会踩的4个坑(必看!)
-
坑1:开机自启失败,提示"ORA-01031: 权限不足":原因是脚本未以oracle用户执行,检查脚本中的「su - oracle -c」命令是否遗漏,或权限未设置正确(chmod +x)。
-
坑2:关机自关闭失效,强制关机导致数据损坏:方案1需确保rc0.d、rc6.d目录下有脚本软链接;方案2需确认ExecStop命令路径正确,重启systemd服务配置。
-
坑3:邮件发送失败,收不到通知:检查sendmail服务是否启动,邮箱授权码是否正确(QQ邮箱授权码需在"设置-账户-POP3/IMAP"中开启),服务器是否能ping通smtp.qq.com。
-
坑4:监听未启动,客户端无法连接:自启脚本中遗漏「lsnrctl start」命令,或dbstart配置文件中ORACLE_HOME_LISTNER路径错误,补充命令或修改路径即可。
五、总结:一步到位,运维省心又高效
整个流程分为3步:先准备环境,再设置Oracle开机自启+关机自关闭,最后配置邮件通知,设置一次,终身受益!
不管是开发、测试还是运维,都能节省每天重复操作的时间,避免因忘记关闭数据库导致的数据损坏,邮件通知更是让你随时随地掌握Oracle状态,无需频繁登录服务器。按照步骤操作,新手也能一次成功,有问题可在评论区留言,看到必回!
💬 评论区互动:你平时是手动启停Oracle还是自动启停?还有哪些Linux运维提升效率的小技巧,欢迎留言分享~