0
0

ShellAgent 0.1.1 (Http接口运行Shell命令)

latermoon 发表于 2013年01月07日 12:26 | Hits: 1638
Tag: 编程技术 | 陌陌架构 | Linux | Python | ShellAgent

花了半天写了ShellAgent 0.1.1,提供http接口运行shell命名,和移动运维客户端结合,服务器信息展示方面大大增强

# -*- coding: utf-8 -*-
# ShellAgent 0.1.1
# @author latermoon
# @since 2013.1.6
# stop all shellagent: pssh -i -h all 'sudo tmux send-keys attach-session -t "shellagent" "C-c" '
# start all shellagent: pssh -i -h all 'sudo tmux new-session -s "shellagent" -d "python /home/scripts/monitor/shellagent.py" '
import BaseHTTPServer
import urlparse
import cgi
import sys, os
import json
import socket
import re
import types

# const
stringType = types.StringType
patternType = type(re.compile('string'))

# hard-coded permissions
allowCommands = [
	re.compile('^ps -(\w)+ \| grep (\w)+$'),
	re.compile('^ps -(\w)+ \| grep (\w)+ \| grep -v grep$'),
	re.compile('^ps -(\w)+ \| grep (\w)+ \| grep -v grep \| wc -l$'),
	'w | grep load',
	'top -n 1',
	'ls', 'ls -al', 'ls ~',
	'df -h',
	'free',
	re.compile('^tail /data/mongolog/momo.log -n (\d)+ \| grep ms$'),
	re.compile('^tail /([A-Za-z0-9/])+.log -n (\d)+$'),
	re.compile('^mongostat --port (\d)+ -n 1 \| grep -v connected$'),
	re.compile('^echo info | redis-cli -h ([A-Za-z0-9\.])+ -p (\d)+$'),
	re.compile('''^ss -an\|grep (\d)+\|awk '{print \$5}'\|awk 'BEGIN{FS=":"}{print \$1}'\|sort \| uniq -c \| sort -rn \|head -n (\d)+$''')
]

# base handler, for output
class BaseApiHandler(BaseHTTPServer.BaseHTTPRequestHandler):

	def displayPlainText(self, text):
		self.send_response(200)
		self.end_headers()
		self.wfile.write(text)

	def displayJson(self, output):
		if not output.has_key('ec'):
			output['ec'] = 0
		if not output.has_key('em'):
			output['em'] = ''
		self.displayPlainText(json.dumps(output))

	def displayErrorJson(self, errcode, errmsg):
		output = {}
		output['ec'] = errcode
		output['em'] = errmsg
		self.displayJson(output)

# exec handler
class WebRequestHandler(BaseApiHandler):
	def do_GET(self):
		self.displayErrorJson(405, 'GET Method NotAllow')

	def do_HEAD(self):
		self.displayErrorJson(405, 'HEAD Method NotAllow')

	def do_POST(self):
		pathObj = urlparse.urlparse(self.path)
		if pathObj.path == '/exec':
			self.handle_exec()
		else:
			self.displayErrorJson(404, 'NotFound')

	def handle_exec(self):
		# read
		form = cgi.FieldStorage(
			fp = self.rfile,
			headers = self.headers,
			environ = {'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type']})

		if not form.has_key('cmd'):
			self.send_error(500)
			return

		cmdinput = form['cmd'].value

		# verify
		allow = False
		for allowCmd in allowCommands:
			cmdType = type(allowCmd)
			if cmdType is stringType:
				if allowCmd == cmdinput:
					allow = True
					break
			elif cmdType is patternType:
				match = allowCmd.match(cmdinput)
				if match:
					allow = True
					break
		if not allow:
			self.displayErrorJson(403, 'NotAllow:%s' % (cmdinput))
			return

		# execute
		print '[exec] [%s] %s' % (self.log_date_time_string(), cmdinput)
		cmdresult = os.popen(cmdinput).read()

		# output
		if form.has_key('fmt') and form['fmt'].value == 'plain':
			# plain
			self.displayPlainText(cmdresult)
		else:
			# json
			output = {}
			output['cmd'] = cmdinput
			output['lines'] = cmdresult.splitlines()
			self.displayJson(output)

# inner IP
host = socket.gethostbyname(socket.gethostname())
port = 8080
demoCmd = 'ls ~'
print 'ShellAgent 0.1.1, by latermoon, bind %s:%d' % (host, port)
print '    '
print '1. JSON(Default): \n'
print '    curl http://%s:%d/exec -d "cmd=%s"' % (host, port, demoCmd)
print '    curl http://%s:%d/exec -d "fmt=json&cmd=%s"' % (host, port, demoCmd)
print '    '
print '    Success: {ec:0, em:"", cmd:"%s", lines:["Desktop", "Downloads"]}' % (demoCmd)
print '    Fail:    {ec:403, em:"NotAllow"}'
print '    '
print '2. Original Output: \n'
print '    curl http://%s:%d/exec -d "fmt=plain&cmd=%s"' % (host, port, demoCmd)
print '    '
print '3. Allow Commands:'
for allowCmd in allowCommands:
	if type(allowCmd) is patternType:
		print '    %s' % (allowCmd.pattern)
	else:
		print '    %s' % (allowCmd)

# start
server = BaseHTTPServer.HTTPServer((host, port), WebRequestHandler)
server.serve_forever()

原文链接: http://blog.latermoon.com/?p=1017

0     0

评价列表(0)