Work towards C SDK (#11). Frenchie is still broken.
[progcomp10.git] / src / link / pexpect / examples / monitor.py
1 #!/usr/bin/env python
2
3 """ This runs a sequence of commands on a remote host using SSH. It runs a
4 simple system checks such as uptime and free to monitor the state of the remote
5 host.
6
7 ./monitor.py [-s server_hostname] [-u username] [-p password]
8     -s : hostname of the remote server to login to.
9     -u : username to user for login.
10     -p : Password to user for login.
11
12 Example:
13     This will print information about the given host:
14         ./monitor.py -s www.example.com -u mylogin -p mypassword
15
16 It works like this:
17     Login via SSH (This is the hardest part).
18     Run and parse 'uptime'.
19     Run 'iostat'.
20     Run 'vmstat'.
21     Run 'netstat'
22     Run 'free'.
23     Exit the remote host.
24 """
25
26 import os, sys, time, re, getopt, getpass
27 import traceback
28 import pexpect
29
30 #
31 # Some constants.
32 #
33 COMMAND_PROMPT = '[#$] ' ### This is way too simple for industrial use -- we will change is ASAP.
34 TERMINAL_PROMPT = '(?i)terminal type\?'
35 TERMINAL_TYPE = 'vt100'
36 # This is the prompt we get if SSH does not have the remote host's public key stored in the cache.
37 SSH_NEWKEY = '(?i)are you sure you want to continue connecting'
38
39 def exit_with_usage():
40
41     print globals()['__doc__']
42     os._exit(1)
43
44 def main():
45
46     global COMMAND_PROMPT, TERMINAL_PROMPT, TERMINAL_TYPE, SSH_NEWKEY
47     ######################################################################
48     ## Parse the options, arguments, get ready, etc.
49     ######################################################################
50     try:
51         optlist, args = getopt.getopt(sys.argv[1:], 'h?s:u:p:', ['help','h','?'])
52     except Exception, e:
53         print str(e)
54         exit_with_usage()
55     options = dict(optlist)
56     if len(args) > 1:
57         exit_with_usage()
58
59     if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
60         print "Help:"
61         exit_with_usage()
62
63     if '-s' in options:
64         host = options['-s']
65     else:
66         host = raw_input('hostname: ')
67     if '-u' in options:
68         user = options['-u']
69     else:
70         user = raw_input('username: ')
71     if '-p' in options:
72         password = options['-p']
73     else:
74         password = getpass.getpass('password: ')
75
76     #
77     # Login via SSH
78     #
79     child = pexpect.spawn('ssh -l %s %s'%(user, host))
80     i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, COMMAND_PROMPT, '(?i)password'])
81     if i == 0: # Timeout
82         print 'ERROR! could not login with SSH. Here is what SSH said:'
83         print child.before, child.after
84         print str(child)
85         sys.exit (1)
86     if i == 1: # In this case SSH does not have the public key cached.
87         child.sendline ('yes')
88         child.expect ('(?i)password')
89     if i == 2:
90         # This may happen if a public key was setup to automatically login.
91         # But beware, the COMMAND_PROMPT at this point is very trivial and
92         # could be fooled by some output in the MOTD or login message.
93         pass
94     if i == 3:
95         child.sendline(password)
96         # Now we are either at the command prompt or
97         # the login process is asking for our terminal type.
98         i = child.expect ([COMMAND_PROMPT, TERMINAL_PROMPT])
99         if i == 1:
100             child.sendline (TERMINAL_TYPE)
101             child.expect (COMMAND_PROMPT)
102     #
103     # Set command prompt to something more unique.
104     #
105     COMMAND_PROMPT = "\[PEXPECT\]\$ "
106     child.sendline ("PS1='[PEXPECT]\$ '") # In case of sh-style
107     i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
108     if i == 0:
109         print "# Couldn't set sh-style prompt -- trying csh-style."
110         child.sendline ("set prompt='[PEXPECT]\$ '")
111         i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
112         if i == 0:
113             print "Failed to set command prompt using sh or csh style."
114             print "Response was:"
115             print child.before
116             sys.exit (1)
117
118     # Now we should be at the command prompt and ready to run some commands.
119     print '---------------------------------------'
120     print 'Report of commands run on remote host.'
121     print '---------------------------------------'
122
123     # Run uname.
124     child.sendline ('uname -a')
125     child.expect (COMMAND_PROMPT)
126     print child.before
127     if 'linux' in child.before.lower():
128         LINUX_MODE = 1
129     else:
130         LINUX_MODE = 0
131
132     # Run and parse 'uptime'.
133     child.sendline ('uptime')
134     child.expect('up\s+(.*?),\s+([0-9]+) users?,\s+load averages?: ([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9]),?\s+([0-9]+\.[0-9][0-9])')
135     duration, users, av1, av5, av15 = child.match.groups()
136     days = '0'
137     hours = '0'
138     mins = '0'
139     if 'day' in duration:
140         child.match = re.search('([0-9]+)\s+day',duration)
141         days = str(int(child.match.group(1)))
142     if ':' in duration:
143         child.match = re.search('([0-9]+):([0-9]+)',duration)
144         hours = str(int(child.match.group(1)))
145         mins = str(int(child.match.group(2)))
146     if 'min' in duration:
147         child.match = re.search('([0-9]+)\s+min',duration)
148         mins = str(int(child.match.group(1)))
149     print
150     print 'Uptime: %s days, %s users, %s (1 min), %s (5 min), %s (15 min)' % (
151         duration, users, av1, av5, av15)
152     child.expect (COMMAND_PROMPT)
153
154     # Run iostat.
155     child.sendline ('iostat')
156     child.expect (COMMAND_PROMPT)
157     print child.before
158
159     # Run vmstat.
160     child.sendline ('vmstat')
161     child.expect (COMMAND_PROMPT)
162     print child.before
163
164     # Run free.
165     if LINUX_MODE:
166         child.sendline ('free') # Linux systems only.
167         child.expect (COMMAND_PROMPT)
168         print child.before
169
170     # Run df.
171     child.sendline ('df')
172     child.expect (COMMAND_PROMPT)
173     print child.before
174     
175     # Run lsof.
176     child.sendline ('lsof')
177     child.expect (COMMAND_PROMPT)
178     print child.before
179
180 #    # Run netstat
181 #    child.sendline ('netstat')
182 #    child.expect (COMMAND_PROMPT)
183 #    print child.before
184
185 #    # Run MySQL show status.
186 #    child.sendline ('mysql -p -e "SHOW STATUS;"')
187 #    child.expect (PASSWORD_PROMPT_MYSQL)
188 #    child.sendline (password_mysql)
189 #    child.expect (COMMAND_PROMPT)
190 #    print
191 #    print child.before
192
193     # Now exit the remote host.
194     child.sendline ('exit')
195     index = child.expect([pexpect.EOF, "(?i)there are stopped jobs"])
196     if index==1:
197         child.sendline("exit")
198         child.expect(EOF)
199
200 if __name__ == "__main__":
201
202     try:
203         main()
204     except Exception, e:
205         print str(e)
206         traceback.print_exc()
207         os._exit(1)
208

UCC git Repository :: git.ucc.asn.au