Chinaunix首页 | 论坛 | 博客
  • 博客访问: 703224
  • 博文数量: 696
  • 博客积分: 15910
  • 博客等级: 上将
  • 技术积分: 7345
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-03 14:34
文章分类

全部博文(696)

文章存档

2012年(263)

2011年(394)

2010年(39)

分类: Python/Ruby

2012-11-17 22:23:42

#!/usr/bin/python

import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)

from pexpect import *
import os, sys, re, commands
from optparse import OptionParser

##exit codes

SPAWNED_BASE_CODE = 100     #exit codes by spawned ssh will be added to 100 
MAIN_ERROR = 1              #main program error
TIME_OUT_ERROR = 2          #ssh timeout
SSH_CON_ERROR = 3           #ssh conn error
PASS_ERROR = 4              #ssh pass error
UNKNOWN_ERROR = 5           #ssh unknwon error

#parse options
usage = "pssh [options] host password command"
parser = OptionParser(usage)
parser.add_option("-u", "--username", dest="user",
                  help="Run using USER, default is current user.")

parser.add_option("-e", "--encrypt-password", action="store_true", dest="encrypt",
                  help="Use this command with a encrypted password, for DMS only."
                  )
parser.add_option("-t", "--timeout",
                 type="int", dest="timeout",
                 help="When execute time exceeds TIMEOUT, force to exit, default value is 30s.")
                 
#don't parse options in command
p_args = sys.argv[1:]
i = 0 
while i < len(p_args):
   if re.compile("-[ut].*").match(p_args[i]):
      if len(p_args[i]) > 2:
         i += 1
      else:
         i += 2
   elif "-e" == p_args[i]:
      i += 1
   elif re.compile("--[eut].*").match(p_args[i]):
      i += 1
   else:
      break

p_cmd = p_args[(i + 2):]
p_args = p_args[:i+2] 

#parse options args.
options, args = parser.parse_args(p_args)
if len(args) < 2:
   print parser.format_help()
   sys.exit(MAIN_ERROR)
user = options.user
timeout = 30 
if options.timeout:
   timeout = options.timeout
host = args[0]
password = args[1]
encrypt = False
if options.encrypt:
   encrypt = options.encrypt

#if encrypt:
#   ret = commands.getstatusoutput('/opt/dms/linux-addon/dms_decrypt ' + password)
#   ret = password
#   if ret[0] != 0:
#      print "decrypt password error."
#      sys.exit(MAIN_ERROR)
#   password = ret[1] 
password = password

cmd = ""
for str in p_cmd:
  cmd += ' ' + str

#expect keys
keys = [ 'authenticity', 
          TIMEOUT, 
          EOF, 
         'pssh_exit', #a little chance, ssh don't echo EOF, while remote cmd exiting.
         '@@@@@@@@@@@@@@@@@@@@', #key failed
         'assword:'
     ]

def clear_ssh_key():
    hostname = host.split('@')[-1]
    keyfile = os.environ['HOME'] + "/.ssh/known_hosts"
    tmpfile = os.environ['HOME'] + "/.ssh/known_hosts.tmp"
    cmd = "sed '/%s/d' %s > %s; mv %s %s" % (hostname, keyfile, tmpfile, tmpfile, keyfile)
    os.system(cmd)

clear_ssh_key()

def do_ssh(ssh_cmd, login_test = False):
    #clear ; at tail of commands
    ssh_cmd=ssh_cmd.strip(';')
    #build command to spawn
    if user :
       command = "ssh -l %s %s '%s; echo $?pssh_exit'"  % (user,host,ssh_cmd)
    else:
       command = "ssh %s '%s; echo $?pssh_exit'"  % (host,ssh_cmd)  

   #spawn it
    try:
      child = spawn(command, [], timeout)
    except Exception, inst:
      print inst
      sys.exit(MAIN_ERROR)
    index = child.expect(keys)
    ##ssh key failed
    if index == 4 or index == 2:
       clear_ssh_key()
       #respawn it
       try:
          child = spawn(command, [], timeout)
       except Exception, inst:
          print inst
          sys.exit(MAIN_ERROR)
       index = child.expect(keys)

    #ssh connect failed
    if index == 2 or index == 4:
       print child.before.strip()
       sys.exit(SSH_CON_ERROR)  

  
    #new connection need authenticity
    if index == 0:
       child.sendline('yes')
       index = child.expect(keys)

    #got 'assword:', and send it.   
    if index == 5:
       child.sendline(password)
       #don't expect password again
       if not login_test:
          del keys[index]
       index = child.expect(keys)

    #got 'TIMEOUT'
    if index == 1:
       print 'run command timeout' 
       child.close()
       sys.exit(TIME_OUT_ERROR) 

    #got 'assword'
    elif index == 5:
       print 'wrong password'
       sys.exit(PASS_ERROR) 

    #complete 
    elif index == 3:
       #login_test successful, return to main
       if login_test:
          return True 
       output = child.before.strip()
       output = output.replace('\r','')
       exitval = output.split('\n')[-1]
       s = output.split('\n')[0:-1]
       for line in s:
           print line   
       try:
         sys.exit(int(exitval) + SPAWNED_BASE_CODE)
       except StandardError, inst:
         print output.split('\n')[-1]
         sys.exit(SPAWNED_BASE_CODE)    #solve problem when use ps in commands 

    #Unknown
    print 'unknown error'
    sys.exit(UNKNOWN_ERROR) 

#do twice ssh login, solve this problem: ssh login a host use non-root user, 
#and then use su - root change to root run something, su - root will prompt 'Password' like
#ssh do.
#login test
do_ssh("echo ok", True)
#do cmd
do_ssh(cmd)

阅读(1401) | 评论(0) | 转发(0) |
0

上一篇:pscp over

下一篇:哈佛图书馆的二十条训言

给主人留下些什么吧!~~