First off, let me say that there is not an original thought in any of this code, since it has all been taken from a number of different articles out on the Internet. The Daemonizing code was taken from the Active State Code Recipes area.
One of my customers has a number of database servers that we would like to monitor and see what the state of the clusters are. The problem is that the clustat command — that used to be run-able by everyone in a lesser version of RHEL — is now only usable by root in RHEL v5.3!. Not wanting to give out root access to everyone, we decided that a quick little custom server that provided the output of the clustat command in XML format would do the trick. Then I just wrote a Ruby program to query all the Clustat XML servers and display the results in a readable format. If there is enough interest, I can post a public version of that program.
Here’s the code:
import sys
import os
import subprocess
import SocketServer
from socket import *
import fcntl
import struct
class CluStatHandler(SocketServer.BaseRequestHandler) :
def handle(self) :
p = subprocess.Popen(['clustat', '-x'], stdout=subprocess.PIPE)
out, err = p.communicate()
self.request.send(out)
def get_ip_address(ifname):
s = socket(AF_INET, SOCK_STREAM)
return inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, struct.pack('256s', ifname[:15]))[20:24])
def main():
HOST = get_ip_address('bond5')
PORT = 2113
server = SocketServer.TCPServer((HOST, PORT), CluStatHandler)
server.serve_forever()
if __name__ == "__main__" :
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError, e:
print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# decouple from parent environment
os.chdir("/")
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent, print eventual PID before
print "Daemon PID %d" % pid
sys.exit(0)
except OSError, e:
print >>sys.stderr, "fork #2 failed: %d (%s)" % (e.errno, e.strerror)
sys.exit(1)
# start the daemon main loop
main()
The main() function sets up the SocketServer, which in turn calls the Handler to go run the clustat command in XML mode (the ‘-x’ parameter), and return the output. Since the servers that my customer has includes several network interfaces, I also had to figure out a way to start the server on the right interface. The get_ip_address function opens a socket on the specified interface, and then queries for its IP address.
A very handy tool to have in your bag of tricks!






