1#!/usr/bin/env python 2 3""" This runs a sequence of commands on a remote host using SSH. It runs a 4simple system checks such as uptime and free to monitor the state of the remote 5host. 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 12Example: 13 This will print information about the given host: 14 ./monitor.py -s www.example.com -u mylogin -p mypassword 15 16It 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 26import os, sys, time, re, getopt, getpass 27import traceback 28import pexpect 29 30# 31# Some constants. 32# 33COMMAND_PROMPT = '[#$] ' ### This is way too simple for industrial use -- we will change is ASAP. 34TERMINAL_PROMPT = '(?i)terminal type\?' 35TERMINAL_TYPE = 'vt100' 36# This is the prompt we get if SSH does not have the remote host's public key stored in the cache. 37SSH_NEWKEY = '(?i)are you sure you want to continue connecting' 38 39def exit_with_usage(): 40 41 print globals()['__doc__'] 42 os._exit(1) 43 44def 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 200if __name__ == "__main__": 201 202 try: 203 main() 204 except Exception, e: 205 print str(e) 206 traceback.print_exc() 207 os._exit(1) 208 209