ToB企服应用市场:ToB评测及商务社交产业平台

标题: Linux平台Oracle开机自启动设置 [打印本页]

作者: 南飓风    时间: 2024-11-14 09:47
标题: Linux平台Oracle开机自启动设置
网上和官方文档已经有不少先容怎样设置开机启动Oracle实例的文章(Linux平台),不过以sysvinit和service这种方式居多。最近遇到了UAT环境的服务器打补丁后需要重启服务器的情况,需要DBA去手工启动Oracle实例的情形,和同事讨论,决定将UAT环境的Oracle实例启停设置成systemd服务,使其开机自启动,避免在服务器打补丁重启的情况下,需要DBA去手工启动Oracle实例。这样可以大大减少工作量。 下面是设置Linux平台Oracle开机自启动的总结性文档,仅供参考。
实验环境:
操作体系版本: Red Hat Enterprise Linux release 8.10 (Ootpa)
数据库版本 : Oracle 19c
方案1

1. 修改oratab文件

修改/etc/oratab的设置,找到如下这样的设置(差别环境,ORACLE_SID以及Oracle安装路径可能差别等,以现实情况为准)
原始值:
  1. gsp:/opt/oracle19c/product/19.3.0/db_1:N
复制代码
修改后:
  1. gsp:/opt/oracle19c/product/19.3.0/db_1:Y
复制代码
在oratab文件中,ORACLE_SIDORACLE_HOME:,设置为Y时,表示答应Oracle实例开机自启动,当设置为N时,则不答应开机自启动。 这个文件里的设置仅仅起一个开关的作用,其实它并不会详细的执行启动和关闭Oracle实例操作. 因为后面的脚本dbstart中会从oratab获取相关值,它类似一个参数设置文件。以是这一步至关重要。
  1. [root@OraPrefTest system]# more /etc/oratab
  2. # This file is used by ORACLE utilities.  It is created by root.sh
  3. # and updated by either Database Configuration Assistant while creating
  4. # a database or ASM Configuration Assistant while creating ASM instance.
  5. # A colon, ':', is used as the field terminator.  A new line terminates
  6. # the entry.  Lines beginning with a pound sign, '#', are comments.
  7. #
  8. # Entries are of the form:
  9. #   $ORACLE_SID:$ORACLE_HOME::
  10. #
  11. # The first and second fields are the system identifier and home
  12. # directory of the database respectively.  The third field indicates
  13. # to the dbstart utility that the database should , "Y", or should not,
  14. # "N", be brought up at system boot time.
  15. #
  16. # Multiple entries with the same $ORACLE_SID are not allowed.
  17. #
  18. #
  19. gsp:/opt/oracle19c/product/19.3.0/db_1:Y
复制代码
简朴方式,可以使用下面命令修改
  1. sed -i 's/:N/:Y/' /etc/oratab
复制代码
2.修改dbstart

dbstart文件的详细路径为:$ORACLE_HOME/bin/dbstart
上述脚本在启动监听时,只启动了默认监听服务(LISTENER),不会启动定名的监听服务,假如你设置的是定名监听的话,那么需要修改脚本,如下所示,假如你使用的是默认的监听服务的话,那么直接跳过这一步。
--修改前
  1.   # Determine location of listener.log
  2.   mkdir -p -- $ORACLE_BASE_HOME/network/log
  3.   LOG=$ORACLE_BASE_HOME/network/log/listener.log
  4.   
  5.   # Start Oracle Net Listener
  6.   if [ -x $ORACLE_HOME/bin/tnslsnr ] ; then
  7.     echo "$0: Starting Oracle Net Listener" >> $LOG 2>&1
  8.     $ORACLE_HOME/bin/lsnrctl start >> $LOG 2>&1 &
  9.     VER10LIST=`$ORACLE_HOME/bin/lsnrctl version | grep "LSNRCTL for " | cut -d' ' -f5 | cut -d'.' -f1`
  10.     export VER10LIST
  11.   else
  12.     echo "Failed to auto-start Oracle Net Listener using $ORACLE_HOME/bin/tnslsnr"
  13.   fi
复制代码
--修改后
此处监听名为gsp,那么我们调解为"$ORACLE_HOME/bin/lsnrctl start gsp"
  1.   # Determine location of listener.log
  2.   mkdir -p -- $ORACLE_BASE_HOME/network/log
  3.   LOG=$ORACLE_BASE_HOME/network/log/listener.log
  4.   
  5.   # Start Oracle Net Listener
  6.   if [ -x $ORACLE_HOME/bin/tnslsnr ] ; then
  7.     echo "$0: Starting Oracle Net Listener" >> $LOG 2>&1
  8.     $ORACLE_HOME/bin/lsnrctl start gsp >> $LOG 2>&1 &
  9.     VER10LIST=`$ORACLE_HOME/bin/lsnrctl version | grep "LSNRCTL for " | cut -d' ' -f5 | cut -d'.' -f1`
  10.     export VER10LIST
  11.   else
  12.     echo "Failed to auto-start Oracle Net Listener using $ORACLE_HOME/bin/tnslsnr"
  13.   fi
复制代码
另外,这里不需要修改别的设置,网上有些文章修改"ORACLE_HOME_LISTNER=$1",其实这个看你的方案与思路,至少这里无需修改别的任何代码。因为调用dbstart脚本的时候,会传入参数。
3.设置dbshut

dbshut文件的详细路径为:$ORACLE_HOME/bin/dbshut
这里跟步调2划一,假如是默认的监听服务,那么也请跳过这一步。
修改前:
  1.   # Determine location of listener.log
  2.   mkdir -p -- $ORACLE_BASE_HOME/network/log
  3.   LOG=$ORACLE_BASE_HOME/network/log/listener.log

  4.   # Stop Oracle Net Listener
  5.   if [ -x $ORACLE_HOME/bin/tnslsnr ] ; then
  6.     echo "$0: Stopping Oracle Net Listener" >> $LOG 2>&1
  7.     $ORACLE_HOME/bin/lsnrctl stop  >> $LOG 2>&1 &
  8.   else
  9.     echo "Failed to auto-stop Oracle Net Listener using $ORACLE_HOME/bin/tnslsnr"
  10.   fi
复制代码
修改后:
  1.   # Determine location of listener.log
  2.   mkdir -p -- $ORACLE_BASE_HOME/network/log
  3.   LOG=$ORACLE_BASE_HOME/network/log/listener.log

  4.   # Stop Oracle Net Listener
  5.   if [ -x $ORACLE_HOME/bin/tnslsnr ] ; then
  6.     echo "$0: Stopping Oracle Net Listener" >> $LOG 2>&1
  7.     $ORACLE_HOME/bin/lsnrctl stop gsp  >> $LOG 2>&1 &
  8.   else
  9.     echo "Failed to auto-stop Oracle Net Listener using $ORACLE_HOME/bin/tnslsnr"
  10.   fi
复制代码
4. 设置systemd服务

在/etc/systemd/system/下创建一个新的systemd服务文件,定名为oracle.service
方式1:
  1. # more oracle.service 
  2. [Unit]
  3. Description=Oracle Database Service
  4. After=network.target

  5. [Service]
  6. Type=forking
  7. User=oracle
  8. Group=oinstall
  9. ExecStart=/opt/oracle19c/product/19.3.0/db_1/bin/dbstart /opt/oracle19c/product/19.3.0/db_1 
  10. ExecStop=/opt/oracle19c/product/19.3.0/db_1/bin/dbshut  /opt/oracle19c/product/19.3.0/db_1
  11. TimeoutStopSec=5min
  12. Restart=on-failure

  13. [Install]
  14. WantedBy=multi-user.target
复制代码
留意:/opt/oracle19c/product/19.3.0/db_1为$ORACLE_HOME,根据现实情况进行调解。
设置完成,执行下面定名后,就可以使用systemctl启动或停止Oracle实例了。
  1. # systemctl daemon-reload
  2. # systemctl enable oracle.service
复制代码
在测试oracle服务的启停前,先确保oracle实例和监听服务已经关闭,假如手工启动的oracle实例,使用下面命令关闭时会异常。详情请见下文"问题1"。
  1. # systemctl start oracle.service
  2. # systemctl status oracle.service
  3. # systemctl stop oracle.service
  4.  
复制代码
此时,你通过命令"systemctl status oracle.service",可以知道查看oracle实例是否正常,你也可以通过$ORACLE_HOME/rdbms/log/startup.log日记查看其实这个日记是在dbshut中生成的。当前测试环境为/opt/oracle19c/product/19.3.0/db_1/rdbms/log/startup.log
方案2

如下所示,我们可以在systemd中引入环境变量,如下所示
  1. # more oracle.service 
  2. [Unit]
  3. Description=Oracle Database Service
  4. After=network.target

  5. [Service]
  6. Type=forking
  7. User=oracle
  8. Group=oinstall
  9. Environment="ORACLE_HOME=/opt/oracle19c/product/19.3.0/db_1"
  10. ExecStart=/opt/oracle19c/product/19.3.0/db_1/bin/dbstart $ORACLE_HOME
  11. ExecStop=/opt/oracle19c/product/19.3.0/db_1/bin/dbshut  $ORACLE_HOME
  12. TimeoutStopSec=5min
  13. Restart=no
  14. RemainAfterExit=yes
  15. KillMode=none

  16. [Install]
  17. WantedBy=multi-user.target
复制代码
我们也可以使用EnvironmentFile来指定环境变量,如下所示,创建文件/home/oracle/dba_scripts/oracle.env,在文件中指定环境变量
  1. ORACLE_HOME=/opt/oracle19c/product/19.3.0/db_1
复制代码
  1. # more oracle.service 
  2. [Unit]
  3. Description=Oracle Database Service
  4. After=network.target

  5. [Service]
  6. Type=forking
  7. User=oracle
  8. Group=oinstall
  9. EnvironmentFile=/home/oracle/dba_scripts/oracle.env
  10. ExecStart=/opt/oracle19c/product/19.3.0/db_1/bin/dbstart $ORACLE_HOME
  11. ExecStop=/opt/oracle19c/product/19.3.0/db_1/bin/dbshut  $ORACLE_HOME
  12. TimeoutStopSec=5min
  13. Restart=no
  14. RemainAfterExit=yes
  15. KillMode=none

  16. [Install]
  17. WantedBy=multi-user.target
复制代码
做完上述操作后,执行下面命令重新加载systemd体系和服务管理器设置
  1. # systemctl daemon-reload
复制代码
方案3

上面的方案有一个问题,就是假如监听服务是定名监听,那么必须修改dbstart或dbshut脚本,假如是一台或两台数据库实例,这样修改倒也没有什么问题。假如服务器多了的话,那么每一台都要修改,那么我们应该考虑不修改这些脚本,通过另外的形式来事项。这个就是方案3的出现的理由。
我们新建一个脚本oracle_start_stop.sh
  1. #!/bin/bash
  2. ###################################################################################################
  3. # Script used to start or stop oracle instance                                                    #
  4. #*************************************************************************************************#
  5. # Version     Autor         Modified Date            Description                                  #
  6. #*************************************************************************************************#
  7. # 1.0       Kerry Kong      2019-09-10        create the shell script.                            #
  8. ###################################################################################################
  9. SUCCESS=0
  10. FAILURE=1
  11.  
  12. # Check the number of parameter.
  13. if [ $# -lt 2 ]; then
  14.   echo "please check the scirpt's parameter"
  15.   exit $FAILURE
  16. fi

  17. STATUS=$1
  18. LISTENER_NAME=$2

  19. if [ $STATUS == 'start' ];then
  20.  $ORACLE_HOME/bin/lsnrctl start $LISTENER_NAME
  21.  $ORACLE_HOME/bin/dbstart $ORACLE_HOME
  22.  exit $SUCCESS
  23. elif [ $STATUS == 'stop' ]; then
  24.  $ORACLE_HOME/bin/lsnrctl stop $LISTENER_NAME
  25.  $ORACLE_HOME/bin/dbshut $ORACLE_HOME
  26.  exit $SUCCESS
  27. else
  28.  echo "the parameter is not correct"
  29. fi
复制代码
新建一个oracle.service的systemd服务文件,如下所示,ExecStart和ExecStop中去调用执行oracle_start_stop.sh文件
  1. # vi oracle.service 
  2. [Unit]
  3. Description=Oracle Database Service
  4. After=network.target

  5. [Service]
  6. Type=forking
  7. User=oracle
  8. Group=oinstall
  9. ExecStart=/home/oracle/dba_scripts/oracle_start_stop.sh start gsp
  10. ExecStop=/home/oracle/dba_scripts/oracle_start_stop.sh stop gsp
  11. TimeoutStopSec=5min
  12. Restart=on-failure

  13. [Install]
  14. WantedBy=multi-user.target
复制代码
设置完成,执行下面定名后,就可以使用systemctl启动或停止Oracle实例了。
  1. # systemctl daemon-reload
  2. # systemctl enable oracle.service
复制代码
问题汇总

问题1: 手工启动oracle实例,使用systemctl stop oracle关闭不了。这是为什么呢?

systemctl是systemd体系和服务管理器的命令行工具,主要用于控制systemd管理的服务。对于那些不是通过 systemd 启动的服务或进程,systemctl 默认情况下是无法直接控制的。比方,假如Oracle实例是通过sqlplus手工启动的话,脚本中不做一些特殊控制或修改,默认情况下,systemctl将无法控制它(关闭它)。
问题2 在oracle.service中使用变量问题
  1. [Unit]
  2. Description=Oracle Database Service
  3. After=network.target

  4. [Service]
  5. Type=forking
  6. User=oracle
  7. Group=dba
  8. ExecStart=$ORACLE_HOME/bin/dbstart
  9. ExecStop=$ORACLE_HOME/bin/dbshut
  10. Restart=on-failure

  11. [Install]
  12. WantedBy=multi-user.target
复制代码
这种情况下,无法获取体系变量$ORACLE_HOME的值。会报如下错误,如下所示:
  1. # systemctl start oracle.service
  2. Failed to start oracle.service: Unit oracle.service has a bad unit file setting.
  3. See system logs and 'systemctl status oracle.service' for details.

  4. # systemctl status oracle.service
  5. ● oracle.service - Oracle Database Service
  6.    Loaded: bad-setting (Reason: Unit oracle.service has a bad unit file setting.)
  7.    Active: inactive (dead)

  8. Oct 21 08:28:30 OraPrefTest systemd[1]: /etc/systemd/system/oracle.service:9: Neither a valid executable name nor an absolute path:$ORACLE_HOME/bin/dbstart
  9. lines 1-5/5 (END)
复制代码
分析如下:
  1. # systemd-analyze verify oracle.service
  2. /etc/systemd/system/./oracle.service:10: Neither a valid executable name nor an absolute path: $ORACLE_HOME/bin/dbstart
复制代码
其实出现这个问题,是因为在systemd中脚本必须使用绝对路径。这个归因于systemd的工作方式和路径解析机制,出于安全(避免路径遍历攻击、防止命令注入等)等方面的缘故原由。
但是可以在脚本后面使用环境变量,如下所示
  1. ExecStart=/opt/oracle19c/product/19.3.0/db_1/bin/dbstart $ORACLE_HOME
  2. ExecStop=/opt/oracle19c/product/19.3.0/db_1/bin/dbshut  $ORACLE_HOME
复制代码
问题3

关于有些版本的一些bug问题,systemd服务里面可能需要设置一些体系变量,如下所示。详细参考官方文档Automatic Stop of Database (dbshut) not working in OL 7 with systemd (Doc ID 2229679.1)。
  1. [Unit]
  2. Description=Oracle Database Start/Stop Service
  3. After=syslog.target network.target local-fs.target remote-fs.target
  4. [Service]
  5. # systemd, by design does not honor PAM limits
  6. # See: https://bugzilla.redhat.com/show_bug.cgi?id=754285
  7. LimitNOFILE=65536
  8. LimitNPROC=16384
  9. LimitSTACK=32M
  10. LimitMEMLOCK=infinity
  11. LimitCORE=infinity
  12. LimitDATA=infinity

  13. Type=simple
  14. User=oracle
  15. Group=oinstall
  16. Restart=no
  17. ExecStartPre=/bin/rm -rf /u01/app/oracle/product/12.2.0/dbhome_1/listener.log
  18. ExecStartPre=/bin/rm -rf /u01/app/oracle/product/12.2.0/dbhome_1/startup.log
  19. ExecStart=/bin/bash /u01/app/oracle/product/12.2.0/dbhome_1/bin/dbstart /u01/app/oracle/product/12.2.0/dbhome_1
  20. RemainAfterExit=yes
  21. ExecStop=/bin/rm -rf /u01/app/oracle/product/12.2.0/dbhome_1/shutdown.log
  22. ExecStop=/bin/bash /u01/app/oracle/product/12.2.0/dbhome_1/bin/dbshut /u01/app/oracle/product/12.2.0/dbhome_1
  23. TimeoutStopSec=5min

  24. [Install]
  25. WantedBy=multi-user.target
复制代码
扫描上面二维码关注我假如你真心觉得文章写得不错,而且对你有所帮助,那就不妨帮忙“推荐"一下,您的“推荐”和”打赏“将是我最大的写作动力!本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接.
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4