linux Web控制台

前段时间做一个hadoop+Spark的性能监控页面时,需要一个web控制台远程登陆到master节点上去,后来发现这方面资料太少,于是自己参照着零散的东西修修改改,终于做出了一个简单的web shell,记录一下以免时间长了忘记。大概像这个样子的:

linux Web控制台_第1张图片

这样就可以在网页上直接访问linux服务器了,初衷是用来远程关闭正在运行的spark任务的,做发现出来之后一般的linux命令都能执行。

首先讲一下后台实现:

1.建立ssh连接,并定义一些流用于收发命令。

2.其次定义是一个接收命令和返回结果的方法,因为linux每次返回一行,所以我这里存入List返回给前台处理。

代码都如下:
package com.java.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;


public class SSHLinux
{
	private String hostname = "11.11.11.15";
	private int port = 22;
	private String username = "root";
	private String password = "123456";
	
	private  Connection conn;
	private  Session sess;
	private  BufferedReader stdout;
	private BufferedReader stderr;
	private PrintWriter pw;
	
	public SSHLinux()
	{
		//使用默认值		
		long t1 = System.currentTimeMillis();
		initSession();
		long t2 = System.currentTimeMillis();
		System.out.println("远程登陆linux,连接耗时:"+(t2-t1)/1000.0+"s");
	}
	
	public SSHLinux(String hostname, int port, String username, String password) 
	{		
		this.hostname = hostname;
		this.port = port;
		this.username = username;
		this.password = password;
	
		long t1 = System.currentTimeMillis();
		initSession();
		long t2 = System.currentTimeMillis();
		System.out.println("远程登陆linux,连接耗时:"+(t2-t1)/1000.0+"s");
	}
	
	//初始化连接并建立虚拟终端
	public void initSession()
	{
		try
		{			
			conn = new Connection(hostname,port);
			conn.connect();
			boolean isAuthenticated = conn.authenticateWithPassword(username, password);
			if (isAuthenticated == false)
				throw new IOException("Authentication failed.");
			
			sess = conn.openSession();
			sess.requestDumbPTY();//建立虚拟终端
			sess.startShell();//打开一个Shell	
			
			stdout = new BufferedReader(new InputStreamReader(new StreamGobbler(sess.getStdout()), StandardCharsets.UTF_8));
			stderr = new BufferedReader(new InputStreamReader(new StreamGobbler(sess.getStderr()), StandardCharsets.UTF_8));
			pw = new PrintWriter(sess.getStdin(),true);// 准备输入命令
			
		}
		catch (IOException e)
		{
			System.out.println("------建立ssh linux连接错误------");
		}
	}
	
	
	public void close()
	{
		try
		{
			stdout.close();
			stderr.close();
			pw.close();
			sess.close();
			conn.close();
		}
		catch (Exception e) 
		{
			System.out.println("------关闭ssh连接错误------");
		}
	
	}

	public List execute(String strcmd)
	{			
		System.out.println("在execute()中接收到命令:"+ strcmd );
		List rstList = new ArrayList();
		try
		{		
			if(strcmd.equals("exit"))
			{
				pw.println(strcmd);// 输入待执行命令	
				close();
				rstList.add("用户退出,关闭连接!!!");
				return rstList;
			}
			
			pw.println(strcmd);// 输入待执行命令					
			
			while (true)
			{
				String line = stdout.readLine();
				if (line == null || line.trim().endsWith("#"))
					break;
				
				System.out.println(line);
				rstList.add(line);
			}
						
		}
		catch (IOException e)
		{
			System.out.println("------连接已经关闭或命令出错------");
		}		
			
		return rstList;		
	}

	
	public static void main(String[] args)
	{
		SSHLinux ssh = new SSHLinux("192.168.0.160",22,"root","123456");
		List list = ssh.execute("pwd");
		System.out.println("list----: "+list);
		//ssh.execute("exit");
	}
}


3.页面后台调用前面初始化方法和执行命令的方法,这个方法叫getLinux(),主要是和前台页面交互。我在这个方法命名为linux,@RequestMapping("/linux"),前台就可以通过linux.do识别了。

首先创建弹出框并初始化:

        /*
	 * 创建按钮弹出框
	 */
	@RequestMapping("/addWindow")
	public ModelAndView goNewAddServer(HttpServletRequest req)
	{ 
		//ssh连接linux---------从xml配置文件中读取参数
		ApplicationContext ct = new ClassPathXmlApplicationContext("applicationContext.xml");
		Permission per = (Permission) ct.getBean("linux");		
		String hostname = per.getIp();
		int port  = per.getPort();
		String username = per.getUsername();
		String password = per.getPassword();
		System.out.println("ssh连接linux---------Permission="+per.toString());
		
		try {
			ssh = new SSHLinux(hostname,port,username,password);
                        //或者将账号写死
			//ssh = new SSHLinux("192.168.1.12",22,"root","123456");
		} catch (Exception e) {			
			e.printStackTrace();
		}		
		return new ModelAndView("/admin/cloudcompute/box");///对应web console页面
	}
其次执行命令,主要是和前台页面交互
        /*
	 * 在linux web shell中执行命令
	 */
	@RequestMapping("/linux")
	@ResponseBody
	private void getLinux(HttpServletRequest request, HttpServletResponse response)throws Exception{
		System.out.println("\n-----------------Linux Shell-----------------\n");		
		String cmd = request.getParameter("code");
		System.out.println("执行命令: "+cmd);
		
		if(ssh!=null)
		{
			List list = new ArrayList();
			if(cmd.length()==0)
			{
				System.out.println("输入为空");
				//list.add("输入为空");
			}
			else if(cmd!="" || cmd.length()!=0 || cmd!=null)
			{
				list = ssh.execute(cmd);	
			}
			
			System.out.println("返回结果list----: "+list);
			
			String result = ""; //{'data:','
			for(String str : list)
			{
				result += str.trim()+"
"; } //result +="'}"; ResponseUtil.write(response, result); //JsonBinder buildNormalBinder = JsonBinder.buildNormalBinder(); //return buildNormalBinder.toJson(result); } else { System.out.println("没有连接,不执行命令"); //return ""; } }//


4.接下来看页面,页面很简单:主要是定义

    列表来接收命令,因为发送的命令占一行,回来的结果为一行或多行,所以
      列表很合适。

      
      
      	控制台											
      
      
      
      

      这是原来的页面中增加的一个模态框,通过按钮触发。当然也可以新建一个页面专门来做控制台,代码都一样,如图:

      <%@ page language="java" contentType="text/html; charset=UTF-8"  pageEncoding="UTF-8"%>
      
      
      
      
      命令行窗口
      
      
      
      
      
      
      
      
      
      
      • ----------------------命令Demo----------------------------
      • 关闭进程方式1:
      • ps -aux | grep test.jar //根据提交的jar包名字来查找进程,再kill -9 [pid]杀掉进程
      • 关闭进程方式2:
      • ps -aux | grep test.jar | kill -9 `awk '{print $2}'` //查找进程id并立即杀掉
      • 关闭进程方式3:
      • kill -9 $(cat my.pid) //前提:提交任务时获取进程号: spark-submit --class demo.WordCount test.jar & echo $!>my.pid
      • ----------------------开始操作----------------------------

      5.页面调用后台代码的部分都是一样的,linux.do就会调转到前面提到的getLinux()方法。

      ok, 本文主要从后台到前台的顺序讲了如何实现一个简单web shell。

      完。

      我准备写一个公众号技术博客,回顾我学大数据以来的个人经验,希望和大家一起每天进步一点点!刚刚开始写,请大家多多支持,如有不足之处多多包含,最后多多关注哈哈哈。

      linux Web控制台_第2张图片

你可能感兴趣的:(Java笔记)