forked from OSchip/llvm-project
209 lines
6.3 KiB
Python
Executable File
209 lines
6.3 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
""" This runs a sequence of commands on a remote host using SSH. It runs a
|
|
simple system checks such as uptime and free to monitor the state of the remote
|
|
host.
|
|
|
|
./monitor.py [-s server_hostname] [-u username] [-p password]
|
|
-s : hostname of the remote server to login to.
|
|
-u : username to user for login.
|
|
-p : Password to user for login.
|
|
|
|
Example:
|
|
This will print information about the given host:
|
|
./monitor.py -s www.example.com -u mylogin -p mypassword
|
|
|
|
It works like this:
|
|
Login via SSH (This is the hardest part).
|
|
Run and parse 'uptime'.
|
|
Run 'iostat'.
|
|
Run 'vmstat'.
|
|
Run 'netstat'
|
|
Run 'free'.
|
|
Exit the remote host.
|
|
"""
|
|
|
|
import os, sys, time, re, getopt, getpass
|
|
import traceback
|
|
import pexpect
|
|
|
|
#
|
|
# Some constants.
|
|
#
|
|
COMMAND_PROMPT = '[#$] ' ### This is way too simple for industrial use -- we will change is ASAP.
|
|
TERMINAL_PROMPT = '(?i)terminal type\?'
|
|
TERMINAL_TYPE = 'vt100'
|
|
# This is the prompt we get if SSH does not have the remote host's public key stored in the cache.
|
|
SSH_NEWKEY = '(?i)are you sure you want to continue connecting'
|
|
|
|
def exit_with_usage():
|
|
|
|
print globals()['__doc__']
|
|
os._exit(1)
|
|
|
|
def main():
|
|
|
|
global COMMAND_PROMPT, TERMINAL_PROMPT, TERMINAL_TYPE, SSH_NEWKEY
|
|
######################################################################
|
|
## Parse the options, arguments, get ready, etc.
|
|
######################################################################
|
|
try:
|
|
optlist, args = getopt.getopt(sys.argv[1:], 'h?s:u:p:', ['help','h','?'])
|
|
except Exception, e:
|
|
print str(e)
|
|
exit_with_usage()
|
|
options = dict(optlist)
|
|
if len(args) > 1:
|
|
exit_with_usage()
|
|
|
|
if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
|
|
print "Help:"
|
|
exit_with_usage()
|
|
|
|
if '-s' in options:
|
|
host = options['-s']
|
|
else:
|
|
host = raw_input('hostname: ')
|
|
if '-u' in options:
|
|
user = options['-u']
|
|
else:
|
|
user = raw_input('username: ')
|
|
if '-p' in options:
|
|
password = options['-p']
|
|
else:
|
|
password = getpass.getpass('password: ')
|
|
|
|
#
|
|
# Login via SSH
|
|
#
|
|
child = pexpect.spawn('ssh -l %s %s'%(user, host))
|
|
i = child.expect([pexpect.TIMEOUT, SSH_NEWKEY, COMMAND_PROMPT, '(?i)password'])
|
|
if i == 0: # Timeout
|
|
print 'ERROR! could not login with SSH. Here is what SSH said:'
|
|
print child.before, child.after
|
|
print str(child)
|
|
sys.exit (1)
|
|
if i == 1: # In this case SSH does not have the public key cached.
|
|
child.sendline ('yes')
|
|
child.expect ('(?i)password')
|
|
if i == 2:
|
|
# This may happen if a public key was setup to automatically login.
|
|
# But beware, the COMMAND_PROMPT at this point is very trivial and
|
|
# could be fooled by some output in the MOTD or login message.
|
|
pass
|
|
if i == 3:
|
|
child.sendline(password)
|
|
# Now we are either at the command prompt or
|
|
# the login process is asking for our terminal type.
|
|
i = child.expect ([COMMAND_PROMPT, TERMINAL_PROMPT])
|
|
if i == 1:
|
|
child.sendline (TERMINAL_TYPE)
|
|
child.expect (COMMAND_PROMPT)
|
|
#
|
|
# Set command prompt to something more unique.
|
|
#
|
|
COMMAND_PROMPT = "\[PEXPECT\]\$ "
|
|
child.sendline ("PS1='[PEXPECT]\$ '") # In case of sh-style
|
|
i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
|
|
if i == 0:
|
|
print "# Couldn't set sh-style prompt -- trying csh-style."
|
|
child.sendline ("set prompt='[PEXPECT]\$ '")
|
|
i = child.expect ([pexpect.TIMEOUT, COMMAND_PROMPT], timeout=10)
|
|
if i == 0:
|
|
print "Failed to set command prompt using sh or csh style."
|
|
print "Response was:"
|
|
print child.before
|
|
sys.exit (1)
|
|
|
|
# Now we should be at the command prompt and ready to run some commands.
|
|
print '---------------------------------------'
|
|
print 'Report of commands run on remote host.'
|
|
print '---------------------------------------'
|
|
|
|
# Run uname.
|
|
child.sendline ('uname -a')
|
|
child.expect (COMMAND_PROMPT)
|
|
print child.before
|
|
if 'linux' in child.before.lower():
|
|
LINUX_MODE = 1
|
|
else:
|
|
LINUX_MODE = 0
|
|
|
|
# Run and parse 'uptime'.
|
|
child.sendline ('uptime')
|
|
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])')
|
|
duration, users, av1, av5, av15 = child.match.groups()
|
|
days = '0'
|
|
hours = '0'
|
|
mins = '0'
|
|
if 'day' in duration:
|
|
child.match = re.search('([0-9]+)\s+day',duration)
|
|
days = str(int(child.match.group(1)))
|
|
if ':' in duration:
|
|
child.match = re.search('([0-9]+):([0-9]+)',duration)
|
|
hours = str(int(child.match.group(1)))
|
|
mins = str(int(child.match.group(2)))
|
|
if 'min' in duration:
|
|
child.match = re.search('([0-9]+)\s+min',duration)
|
|
mins = str(int(child.match.group(1)))
|
|
print
|
|
print 'Uptime: %s days, %s users, %s (1 min), %s (5 min), %s (15 min)' % (
|
|
duration, users, av1, av5, av15)
|
|
child.expect (COMMAND_PROMPT)
|
|
|
|
# Run iostat.
|
|
child.sendline ('iostat')
|
|
child.expect (COMMAND_PROMPT)
|
|
print child.before
|
|
|
|
# Run vmstat.
|
|
child.sendline ('vmstat')
|
|
child.expect (COMMAND_PROMPT)
|
|
print child.before
|
|
|
|
# Run free.
|
|
if LINUX_MODE:
|
|
child.sendline ('free') # Linux systems only.
|
|
child.expect (COMMAND_PROMPT)
|
|
print child.before
|
|
|
|
# Run df.
|
|
child.sendline ('df')
|
|
child.expect (COMMAND_PROMPT)
|
|
print child.before
|
|
|
|
# Run lsof.
|
|
child.sendline ('lsof')
|
|
child.expect (COMMAND_PROMPT)
|
|
print child.before
|
|
|
|
# # Run netstat
|
|
# child.sendline ('netstat')
|
|
# child.expect (COMMAND_PROMPT)
|
|
# print child.before
|
|
|
|
# # Run MySQL show status.
|
|
# child.sendline ('mysql -p -e "SHOW STATUS;"')
|
|
# child.expect (PASSWORD_PROMPT_MYSQL)
|
|
# child.sendline (password_mysql)
|
|
# child.expect (COMMAND_PROMPT)
|
|
# print
|
|
# print child.before
|
|
|
|
# Now exit the remote host.
|
|
child.sendline ('exit')
|
|
index = child.expect([pexpect.EOF, "(?i)there are stopped jobs"])
|
|
if index==1:
|
|
child.sendline("exit")
|
|
child.expect(EOF)
|
|
|
|
if __name__ == "__main__":
|
|
|
|
try:
|
|
main()
|
|
except Exception, e:
|
|
print str(e)
|
|
traceback.print_exc()
|
|
os._exit(1)
|
|
|