如何用kill安全殺掉clusterware

我們知道,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東西的情況下殺死。有興趣的朋友可以自行實驗。)


<-------------先寫到這,我們成功殺死了根ohasd.bin,剩下的就容易的多,剩下的慢慢補上-------->
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章