我们知道,
11g
R2中,集群引入了很多新的进程。并且一旦集群完全启动,我们很难用单用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东西的情况下杀死。有兴趣的朋友可以自行实验。)
<-------------先写到这,我们成功杀死了根ohasd.bin,剩下的就容易的多,剩下的慢慢补上-------->
一是 因为这些进程互相依赖守护,不管你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东西的情况下杀死。有兴趣的朋友可以自行实验。)
<-------------先写到这,我们成功杀死了根ohasd.bin,剩下的就容易的多,剩下的慢慢补上-------->