只用KILL命令安全高效的关闭clusterwar

转自:http://www.itpub.net/thread-1620414-1-1.html


我们知道,11gR2中,集群引入了很多新的进程。并且一旦集群完全启动,我们很难用单用linux的kill命令去关闭这些进程。

一是 因为这些进程互相依赖守护,不管你kill了哪些进程,这些进程立刻都会被重新启动。 
二是 如果kill的顺序不对,轻则宕机重启,重则可能产生不一致性。(脑裂)

而实际工作中,有些情况下,即使crsctl stop crs -f 也会遇到hang住的情况,所以这种情况下,我们还是得借助linux的KILL命令去杀死进程。
下面我们就来模拟一个极端的情况,对于一个正常工作的,所有服务都启动了的集群中的某节点,如何在不touch任何 oracle 相关的东东的前提下,只用kill命令,就安全高效的清理此节点上所有的clusterware资源?

下面我们来演示下:
[root@node1 ~]# ps -ef|grep d.bin
root       462     1  0 10:27 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/octssd.bin
root       464     1  0 10:27 ?        00:00:02 /prod/grid/app/11.2.0/grid/bin/crsd.bin reboot
grid       470     1  0 10:27 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/gpnpd.bin
root       538     1  0 10:28 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/oclskd.bin
oracle     599     1  0 10:28 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/oraagent.bin
root       603     1  0 10:28 ?        00:00:01 /prod/grid/app/11.2.0/grid/bin/orarootagent.bin
root      1280     1  1 10:31 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/ohasd.bin reboot
grid      1336     1  0 10:31 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/oraagent.bin
root      1340     1  0 10:31 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/orarootagent.bin
root      1342     1  5 10:31 ?        00:00:02 /prod/grid/app/11.2.0/grid/bin/cssdagent
....省略剩下的若干进程...


我们随便来kill排在前几号的进程:464 470 538 599 603, 对应crsd|gpnpd|oclskd|oraagent|orarootagent
[root@node1 ~]# kill -9 464 470 538 599 603
然后检查:
[root@node1 ~]#  ps -ef|grep -v grep|egrep 'crsd|gpnpd|oclskd|oraagent|orarootagent'
grid      1336     1  0 10:31 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/oraagent.bin
root      1340     1  0 10:31 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/orarootagent.bin
grid      1481     1  0 10:32 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/gpnpd.bin
root      1500     1  1 10:32 ?        00:00:01 /prod/grid/app/11.2.0/grid/bin/crsd.bin reboot
root      1530     1  0 10:32 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/oclskd.bin
root      1584     1  0 10:32 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/orarootagent.bin
grid      1587     1  0 10:32 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/oraagent.bin
oracle    1592     1  0 10:32 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/oraagent.bin
我们看到,随便乱kill是没有作用的,这些进程如烧不尽的野草般又生长出来。
并且注意进程的启动时间有了变化,可以确定这是我们kill后重新启动起来的。

这样盲目的kill是不行的,我们很快能想到,要kill的话,就必须从根开始。根若不死,则就会一生二,二生三,三生万物的把整个进群结构给重新演化出来。
根在哪?  答:ohasd

那么下一步是否先从这个根ohasd开始杀起?
可是,这么明显的漏洞,oracle能没想到吗? 对于这最脆弱的根,oracle使用了守护进程进行保护,一旦死亡,会被自动重新启动。所以这最后的弱点也没有了。

下面我们看到,杀死ohasd.bin,立刻被init.ohasd重新生成,我们kill init.ohasd进程,也重新被PID=1的根进程给重新respawn起来:
[root@node1 ~]# ps -ef|grep ohasd |grep -v grep
root       750     1  0 10:28 ?        00:00:00 /bin/sh /etc/init.d/init.ohasd run
root      1280     1  0 10:31 ?        00:00:01 /prod/grid/app/11.2.0/grid/bin/ohasd.bin reboot
[root@node1 ~]# kill -9 1280                            ---先尝试杀死ohasd.bin
[root@node1 ~]# ps -ef|grep ohasd |grep -v grep         ---没用,注意时间和PID的改变,说明又被重新启动
root       750     1  0 10:28 ?        00:00:00 /bin/sh /etc/init.d/init.ohasd run
root      2294   750 12 10:52 ?        00:00:00 /prod/grid/app/11.2.0/grid/bin/ohasd.bin restart
[root@node1 ~]# kill -9 750                             ---尝试杀死守护进程init.ohasd
[root@node1 ~]# ps -ef|grep ohasd |grep -v grep         ---没用,注意时间和PID的改变,说明又被重新启动
root      2294     1  3 10:52 ?        00:00:01 /prod/grid/app/11.2.0/grid/bin/ohasd.bin restart
root      2462     1  0 10:53 ?        00:00:00 /bin/sh /etc/init.d/init.ohasd run



那么真的没有办法了吗?想要摧毁敌人,先要了解敌人。
下面简单介绍下关于ohasd的一些知识点:
1./etc/init.d/init.ohasd:也就是大家看到的守护进程,但是要注意,这个守护进程并不会在操作系统重新启动时自动启动ohasd服务的进程。

2.ohasd.bin:真正的d.bin进程,负责生成几个最主要的agent进程(oraagent, orarootagent, cssdagent),从而由这些agent去生万物。

3./etc/init.d/ohasd 负责在系统启动时调用一次自动启动ohasd服务。   注意,这个服务只会在系统启动时候自动调用一次自动启动ohasd,之后再也没有任何作用,直到下一次重启。在此期间ohasd.bin的监视交给init.ohasd守护进程负责,一旦发现ohasd.bin意外死亡,将由/etc/init.d/init.ohasd 守护进程负责重启。
你在系统日志中看到的"May 28 09:52:10 node1 root:  Oracle  HA daemon is enabled for autostart.",  就是由/etc/init.d/ohasd产生。

4./rc.d/rc3.d/S96ohasd, ./rc.d/rc5.d/S96ohasd, ./rc.d/rc6.d/K19ohasd, ./rc.d/rc1.d/K19ohasd.  这些都是/etc/init.d/ohasd的快捷方式, 负责在系统启动时调用一次自动启动ohasd服务。

5.$GRID_HOME/bin/ohasd.    你在日志中看到的诸如以下信息都由此脚本负责写入:
May 28 09:52:12 node1 logger: exec /prod/grid/app/11.2.0/grid/perl/bin/perl -I/prod/grid/app/11.2.0/grid/perl/lib /prod/grid/app/11.2.0/grid/bin/crswrapexece.pl /prod/g
rid/app/11.2.0/grid/crs/install/s_crsconfig_node1_env.txt /prod/grid/app/11.2.0/grid/bin/ohasd.bin "reboot"
May 28 09:52:13 node1 /prod/grid/app/11.2.0/grid/bin/crswrapexece.pl[30866]: executing "/prod/grid/app/11.2.0/grid/bin/ohasd.bin reboot"


6. 简单的关联关系来描述下:
/etc/init.d/ohasd     (系统启动时运行一次启动负责ohasd.bin初始启动) ----->  $GRID_HOME/bin/crsctl   |
                                                                                                      |  =====>$GRID_HOME/bin/ohasd ====> ohasd.bin
/etc/init.d/init.ohasd(系统启动后监视ohasd.bin,发现失败则重启    ) ----->                          |


我们可以看到,大家熟知的init.ohasd守护进程并不是负责在系统启动时候启动ohasd服务的,所以这也回答了一些朋友的疑问:
为什么即使关闭了cluster后重启节点后集群仍然会重新启动。 如果是是由init.ohasd负责启动的那为什么一定要重启操作系统后才能自动启动?

答案就是操作系统启动时ohasd的启动由/etc/init.d/ohasd负责的而不是/etc/init.d/init.ohasd。

那么系统启动时由/etc/init.d/ohasd会启动ohasd.bin, 这不会和也负责保护ohasd的/etc/init.d/init.ohasd冲突吗?
所以 /etc/init.d/init.ohasd有自己的一套判断机制,可以判断当前是否处在操作系统重新启动时/etc/init.d/ohasd 正在开始启动ohasd.bin但是还尚未启动的过程中,如果是处在这一过程,那么
/etc/init.d/init.ohasd就会进行等待,而不会再去尝试启动ohasd.bin。

所以我们想要永久性的杀死ohasd.bin并阻止init.ohasd守护启动进程重新启动它的方法也落在此处,那就是让init.ohasd误以为当前状体是处于一个刚刚重启,/etc/init.d/ohasd  尚未启动ohasd.bin的状态中。
这样自然init.ohasd就会一直等待下去,而不再尝试重启ohasd.bin。

原理有点晦涩,但是知道了这个原理后,真正的解决方法很简单:
[root@node1 log]# ps -ef|grep ohasd
root     32563     1  0 10:25 ?        00:00:00 /bin/sh /etc/init.d/init.ohasd run
root     32693 32563  0 10:25 ?        00:00:01 /prod/grid/app/11.2.0/grid/bin/ohasd.bin restart
[root@node1 log]# kill -9 32563; kill -9 32693  
[root@node1 log]# ps -ef|grep ohasd
root       750     1  0 10:28 ?        00:00:00 /bin/sh /etc/init.d/init.ohasd run
root       768   750  0 10:28 ?        00:00:00 /bin/sh /etc/init.d/init.ohasd run
[root@node1 log]# ps -ef|grep ohasd
root       750     1  0 10:28 ?        00:00:00 /bin/sh /etc/init.d/init.ohasd run  ---ohasd.bin被成功杀死并且不再启动,只剩下init.ohasd孤单的运行着

注意红字部分 kill -9 32563; kill -9 32693 ,通过这种kill方式,我们就成功杀死了ohasd.bin ,并且使得init.ohasd 成功落在了上面黑体字段所描述的那种特殊状态中,不会再次尝试重启ohasd.bin。
(当然,如果只是简单的想失效init.ohasd,更简单些我们可以给ohasdrun文件写入STOP标志,或者直接从inittab中注释掉init.ohasd然后生效更改,
可是这么一来就失去了本文的目的,也称不上是在不动任何oracle东西的情况下杀死。有兴趣的朋友可以自行实验。)

你可能感兴趣的:(RAC)