サーバーの状態をブラウザから確認できるPythonスクリプト

#説明

ブラウザからサーバーの状態を監視する。
Pythonの入門書籍を参考にして、それを少し改良して作った。
たいしたものではないですが、せっかく作ったので残しておく。


#画面

サーバーで実行すると8000ポートで待ち受ける。
ブラウザで開くとメニューが表示される。

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/33116/ed8a0d7f-b316-acd2-5982-ec8b944a861a.png)

コマンドをクリックするとブラウザ上で結果を見れる。

![無題2.png](https://qiita-image-store.s3.amazonaws.com/0/33116/08156430-d283-1d17-d7c0-e6a217ddd3cc.png)


#ソースコード

	# coding: UTF-8

	import BaseHTTPServer, shutil, os
	from cStringIO import StringIO

	class  MyHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
	    # 提供するサービスのHTTPパスおよびコマンドラインコマンド

	    cmds = { '/free': 'free',
	            '/cpuinfo' : 'cat /proc/cpuinfo',
	            '/netstat' : 'netstat -anp',
	            '/netstat-nlt' : 'netstat -nlt',
	            '/uptime' : 'uptime',
	            '/vmstat' : 'vmstat',
	            '/df' : 'df -h',
	            '/sar' : 'sar',
	            '/hostname' : 'hostname',
	            '/date' : 'date',
	            '/ps' : 'ps aux',
	            '/iostat' : 'iostat',
	            '/pstree' : 'pstree',
	            '/ifconfig' : 'ifconfig',
	            '/who' : 'who'}

	    def do_GET(self):
	        # GETリクエストへのサービス

	        # レスポンスやコンテンツタイプを指定するためにheadメソッドを呼び出しておく。
	        f = self.send_head()

	        # ファイルオブジェクトが帰ってきていればレスポンスチェックが通り、200OKなのでボディを作成する。
	        # なお今回はGETなので上記のfは使わないで下記のように新しく上書きする。
	        if f:
	            f = StringIO()

	            # マシン名を取得する
	            machine = os.popen("hostname").readlines()[0]

	            # /ならばインデックスを作成して返すだけ
	            if self.path == "/":
	                heading = "Select a command to run on %s" % (machine)
	                body = self.getMenu()

	            # コマンド指定の場合は実際にコマンドを実行して返す。
	            else:
	                heading = "Execution of ``%s'' on %s" % ( self.cmds[self.path], machine )
	                cmd = self.cmds[self.path]
	                body = '<a href="/">Main Menu</a><pre>%s</pre>\n' % os.popen(cmd).read()

	            f.write("<html><head><title>%s</title></head>\n" % (heading) )
	            f.write("<body><h1>%s</h1>\n" % (heading))
	            f.write(body)
	            f.write("</body></html>\n")
	            f.seek(0)
	            self.copyfile(f, self.wfile)
	            f.close()
	        return f

	    def do_HEAD(self):
	        # HEADリクエストへのサービス
	        f = self.send_head()
	        if f:
	            f.close()

	    def send_head(self):
	        path = self.path
	        if not path in ["/"] + self.cmds.keys():
	            head = 'Command "%s" not found. Try one of these:<ul>' % path
	            msg = head + self.getMenu()
	            self.send_error(404, msg)
	            return None
	        self.send_response(200)
	        self.send_header("Content-type", "text/html; charset=UTF-8")
	        self.end_headers()
	        f = StringIO()
	        f.write("A test %s\n" % self.path)
	        f.seek(0)
	        return f

	    def getMenu(self):
	        keys = self.cmds.keys()
	        keys.sort()
	        msg = []
	        for k in keys:
	            msg.append('<li><a href="%s">%s => %s</a></li>' % (k,k, self.cmds[k]))

	        msg.append("</ul>")
	        return "\n".join(msg)

	    def copyfile(self, source, outputfile):
	        shutil.copyfileobj(source, outputfile)

	def main(HandlerClass = MyHTTPRequestHandler, ServerClass = BaseHTTPServer.HTTPServer):
	    BaseHTTPServer.test(HandlerClass, ServerClass)

	if __name__ == '__main__':
	    main()