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
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.
13 This will print information about the given host:
14 ./monitor.py -s www.example.com -u mylogin -p mypassword
17 Login via SSH (This is the hardest part).
18 Run and parse 'uptime'.
26 import os, sys, time, re, getopt, getpass
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'
39 def exit_with_usage():
41 print globals()['__doc__']
46 global COMMAND_PROMPT, TERMINAL_PROMPT, TERMINAL_TYPE, SSH_NEWKEY
47 ######################################################################
48 ## Parse the options, arguments, get ready, etc.
49 ######################################################################
51 optlist, args = getopt.getopt(sys.argv[1:], 'h?s:u:p:', ['help','h','?'])
55 options = dict(optlist)
59 if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
66 host = raw_input('hostname: ')
70 user = raw_input('username: ')
72 password = options['-p']
74 password = getpass.getpass('password: ')
79 child = pexpect.spawn('ssh -l %s %s'%(user, host))
80 i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, COMMAND_PROMPT, '(?i)password'])
82 print 'ERROR! could not login with SSH. Here is what SSH said:'
83 print child.before, child.after
86 if i == 1: # In this case SSH does not have the public key cached.
87 child.sendline ('yes')
88 child.expect ('(?i)password')
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.
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])
100 child.sendline (TERMINAL_TYPE)
101 child.expect (COMMAND_PROMPT)
103 # Set command prompt to something more unique.
105 COMMAND_PROMPT = "\[PEXPECT\]\$ "
106 child.sendline ("PS1='[PEXPECT]\$ '") # In case of sh-style
107 i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
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)
113 print "Failed to set command prompt using sh or csh style."
114 print "Response was:"
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 '---------------------------------------'
124 child.sendline ('uname -a')
125 child.expect (COMMAND_PROMPT)
127 if 'linux' in child.before.lower():
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()
139 if 'day' in duration:
140 child.match = re.search('([0-9]+)\s+day',duration)
141 days = str(int(child.match.group(1)))
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)))
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)
155 child.sendline ('iostat')
156 child.expect (COMMAND_PROMPT)
160 child.sendline ('vmstat')
161 child.expect (COMMAND_PROMPT)
166 child.sendline ('free') # Linux systems only.
167 child.expect (COMMAND_PROMPT)
171 child.sendline ('df')
172 child.expect (COMMAND_PROMPT)
176 child.sendline ('lsof')
177 child.expect (COMMAND_PROMPT)
181 # child.sendline ('netstat')
182 # child.expect (COMMAND_PROMPT)
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)
193 # Now exit the remote host.
194 child.sendline ('exit')
195 index = child.expect([pexpect.EOF, "(?i)there are stopped jobs"])
197 child.sendline("exit")
200 if __name__ == "__main__":
206 traceback.print_exc()