прямой доступ к SGA / способ 3: python + ctypes

 

 

 
Для python'а написан "волшебный" модуль ctypes, который позволяет вызывать функции из динамических библиотек напрямую, без написания wrapper'а. Грех не воспользоваться такой возможностью. :)

 

Ниже код (linux 2.4, glibc2, python 2.3.4, ctypes 0.6.3) с использованием ctypes:

#!/usr/bin/env python
# readSGA.py
# http://www.oracledba.ru

from ctypes import *

shmid     = 131074
sgaBase   = 0x50000000
ksuseAddr = 0x5B2B1680
rowCount  = 170
rowSize   = 2408

class SGAException(Exception):
  pass

class ReadSGA:
  libc = cdll.LoadLibrary("/lib/libc.so.6")
  def __init__(self,shmid,sgaBase):
    self.mem = self.libc.shmat(shmid,sgaBase,010000) # 010000 == SHM_RDONLY
    if self.mem == -1:
      raise SGAException, "can't attach to SGA with id %s" % shmid
  def read1(self,addr): 
    val = (c_byte * 1).from_address(addr)
    return val[0]
  def read2(self,addr):
    val = (c_byte * 2).from_address(addr)
    return val[0]+val[1]*256
  def read4(self,addr):
    val = (c_long * 1).from_address(addr)
    return val[0]
  def reads(self,addr,size):
    val = (c_char * size).from_address(addr)
    return val.value
  def __del__(self):
    self.libc.shmdt(self.mem)

def readstatus(statusid,ksuseflg):
  if (statusid & 11 == 1):
    status = 'ACTIVE'
  elif (statusid & 11 == 0):
    if (ksuseflg & 4096 == 0):
      status = 'INACTIVE'
    else:
      status = 'CACHED'
  elif (statusid & 11 == 2):
    status = 'SNIPED'
  elif (statusid & 11 == 3):
    status = 'SNIPED'
  else:
    status = 'KILLED'
  return status

readSGA = ReadSGA(shmid,sgaBase)

print "'select from v$session' made by reading SGA directly:"
print "       SID    SERIAL# USERNAME                       STATUS"
print "---------- ---------- ------------------------------ --------"

memaddr = ksuseAddr
for i in range(1,rowCount):
  ksspaflg = readSGA.read1(memaddr+1)
  ksuseflg = readSGA.read4(memaddr+1388)
  sid      = i
  serial   = readSGA.read2(memaddr+1382)
  username = readSGA.reads(memaddr+67,30)
  statusid = readSGA.read1(memaddr+1420)
  status   = readstatus(statusid,ksuseflg)
  if (ksspaflg & 1 != 0) and (ksuseflg & 1 != 0):
    print "%10d %10d %-30s %-8s" % (sid,serial,username,status)
  memaddr += rowSize

Если Вы подставите свои значения в начало скрипта, то у Вас получится работающий скрипт для "моментального" просмотра сессий без участия Oracle (но только до следующей перезагрузки Oracle'а :) )




назад далее