import repository from arizona
[raven.git] / 2.0 / python / logging / stracedaemon.py
1 #! /usr/bin/env python
2
3 """
4 <Program Name>
5    stracedaemon.py
6
7 <Started>
8    February 3, 2007
9
10 <Author>
11    Programmed by Jeffry Johnston
12
13 <Purpose>
14    Collects packet information from strace and saves as files in one hour
15    increments.
16
17 """
18
19 #           [option, long option,  variable,   action,  data,     default, metavar,   description]
20 """arizonaconfig
21    options=[
22             ["",     "--logdir",   "logdir",   "store", "string", "/tmp",  "DIR",     "log file directory (default: /tmp)"],
23             ["",     "--interval", "interval", "store", "int",    3600,    "SECONDS", "wait at least this number of seconds before opening a new log file (default 3600)"]
24            ]
25    includes=[]        
26 """
27
28 import arizonaconfig
29 import signal
30 import arizonageneral
31 import os
32 import sys
33 import time
34 import storkerror
35 import arizonareport
36 import time
37
38 done = False
39 pipe = None
40
41
42
43
44
45 def handler_sighup(signum, frame):
46     """
47     <Purpose>
48        Intercepts the HUP signal.
49     """
50     global done, pipe
51
52     try:
53        pipe.flush()
54        pipe.close()
55     except:
56        pass
57     pipe = None
58     done = True
59
60
61 LOGSUFFIX = "^strac2"
62 CURRENTFILE = "current.strac2"
63 DAEMONNAME = "straced"
64 DAEMONPIDFILE = "/tmp/strace.pid"
65
66 # the name of the file that contains the pid that we want to monitor with
67 # strace
68 INPUT_PIDFILE = "/var/run/stork_nest_comm.py.pid"
69
70 def main():
71    global done, pipe
72
73    # parse command line and options
74    args = arizonaconfig.init_options(module="stracedaemon.py", version="2.0")
75
76    # run as a daemon
77    arizonageneral.make_daemon(DAEMONNAME)
78
79    # make it easy to kill the daemon
80    outfile = open(DAEMONPIDFILE, "w")
81    outfile.write(str(os.getpid()))
82    outfile.close()
83
84    # check to make sure the service we want to monitor exists
85    if not os.path.exists(INPUT_PIDFILE):
86        # sleep a few seconds and try again, just in case stork_nest_comm
87        # was launched, but has not yet written its pidfile
88        time.sleep(10)
89        if not os.path.exists(INPUT_PIDFILE):
90            # raise an exception to generate an error report
91            raise Exception, "the stork nest is not running"
92            # the following does not happen
93            arizonareport.send_error(0, "the stork nest is not running")
94            sys.exit(-1)
95
96    # get the pid we want to monitor from INPUT_PIDFILE
97    input_pidfile = open(INPUT_PIDFILE)
98    input_pid = input_pidfile.read()
99    input_pidfile.close()
100
101    arizonareport.send_out(0, "monitoring pid " + str(input_pid))
102
103    command = '(strace -f -ttt -e trace=network -p ' + str(input_pid)+ ' 2>&1 1>/dev/null)' + \
104              ' | (egrep "AF_INET")'
105
106 #             ' | egrep "connect\([0-9]+, \{sa_family=AF_INET.* = 0" 2>/dev/null' + \
107 #             ' | fgrep -v "127.0.0.1"' + \
108 #             ' | awk \'"*" { gsub("(\\[pid )|(\\])|(sin_port=htons\\()|(\\),)|(sin_addr=inet_addr\\(.)|(.\\)\\},)","", $0); print $1 " " $2 " " $5 " " $6; }\''
109
110
111    arizonareport.send_out(0, "executing: " + command)
112
113    # set up I/O
114    # XXX run the command
115    pipe = os.popen(command, "r")
116
117    # set up hangup signal handler
118    signal.signal(signal.SIGHUP, handler_sighup)
119
120    lasttime = 0
121
122    while not done:
123       # is it time to change log file?
124       currtime = time.time()
125       if currtime - lasttime >= arizonaconfig.get_option("interval"):
126          lasttime = currtime
127
128          # build filename
129          filename = None
130          try:
131             filename = arizonageneral.gethostname()
132          except:
133             pass
134          if filename == None:
135             filename = "unknown_host"
136          try:
137             username = arizonageneral.getusername()
138          except:
139             username = "unknown_user"
140          filename = arizonaconfig.get_option("logdir") + "/" + filename \
141                     + "^" + username + "^" + str(currtime) + LOGSUFFIX
142
143          # close old file
144          try:
145             outfile.flush()
146          except:
147             pass
148          try:
149             outfile.close()
150          except:
151             pass
152             
153          # create current.packetlog file
154          try:
155             tempfile = open(arizonaconfig.get_option("logdir") + "/" + CURRENTFILE, "w")
156             tempfile.write(filename)
157             tempfile.close()
158          except:
159             pass
160             
161          # open new file   
162          try:    
163             outfile = open(filename, "a")
164          except:   
165             pass
166    
167       # read stdin
168       if not done:    
169          try:
170             line = pipe.readline()
171          except:
172             done = True
173
174       # write to file
175       if not done:    
176          try:
177             outfile.write(line)
178          except: 
179             pass   
180       if not done:    
181          try:
182             outfile.flush()
183          except: 
184             pass   
185    
186       #dont eat up cycles
187       time.sleep(1)
188
189    # clean up
190    try:
191       outfile.close()
192    except: 
193       pass   
194       
195    os.system("/bin/rm -f " + DAEMONPIDFILE + " &> /dev/null")
196
197
198
199
200
201 if __name__ == "__main__":
202    # prepare error reporting tool
203    storkerror.init_error_reporting("stracedaemon.py")
204
205    # call main
206    main()