网络编程实现远程执行shell指令

20 篇文章 2 订阅
7 篇文章 0 订阅


今天下午,忙完手里的活,就在想扩展一下之前的java执行shell。之前是通过http请求,发送指令,后端执行,现在想的是网络编程创建服务端,客户端自己run或使用工具,拦截一部分人吧。这么做其实是适合很多所谓的堡垒机,免得无权限登录,但是又需要执行一些命令。废话不多说,直接上码。
一、shell执行工具类


import org.apache.commons.lang.ArrayUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * @author zhengwen
 */
public class ProcessUtil {
    /**
     * 执行shell
     * @param shStrArr 指令数组
     * @return 执行结果/反馈
     * @throws Exception
     */
    public static String runShell(String[] shStrArr) throws Exception {
        StringBuffer sb = new StringBuffer();
        sb.append("-----------result--------------");
        sb.append("\n");

        Process process = null;
        //List<String> processList = new ArrayList<String>(); 多命令
        try {
            if (!ArrayUtils.isEmpty(shStrArr)) {
                String sh = "";
                for (int i = 0; i < shStrArr.length; i++) {
                    String tmpSh = shStrArr[i];
                    sh += tmpSh;
                    if (i != shStrArr.length - 1) {
                        sh += "&&";
                    }
                }
                String[] cmd;
                //支持多操作系统
                String osName = System.getProperty("os.name");
                if (osName.startsWith("Windows")) {
                    cmd = new String[3];
                    cmd[0] = "cmd.exe";
                    cmd[1] = "/C";
                    cmd[2] = sh;
                    sh = "cmd.exe /C " + sh;
                } else if (osName.startsWith("Linux") || osName.toLowerCase().startsWith("centos")) {
                    //linux
                    cmd = new String[3];
                    cmd[0] = "/bin/sh";
                    cmd[1] = "-c";
                    cmd[2] = sh;
                    sh = "/bin/sh -c " + sh;
                } else {
                    cmd = new String[1];
                    cmd[0] = sh;
                }

                //process = Runtime.getRuntime().exec(cmd);
                process = Runtime.getRuntime().exec(sh);

                BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream(), "gb2312"));
                String line = "";
                while ((line = input.readLine()) != null) {
                    //processList.add(line);
                    sb.append(line);
                    sb.append("\n");
                }
                process.waitFor();
                input.close();
            }

        } catch (Exception e) {
            sb.append(e.getMessage());
        }

        return sb.toString();
    }

    public static void main(String[] args) {
        String[] shStr = {"cmd.exe /C dir d:", "cmd.exe /C dir d:\\application"};

        String rs = null;
        try {
            rs = ProcessUtil.runShell(shStr);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(rs);
    }

}

二、服务端


import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Set;

/**
 * @author zhengwen
 **/
public class SocketServer {
    /**
     *    解码buffer
     */
    private Charset cs = Charset.forName("UTF-8");
    /**
     * 接受数据缓冲区
     */
    private static ByteBuffer sBuffer = ByteBuffer.allocate(1024);
    /**
     * 发送数据缓冲区
     */
    private static ByteBuffer rBuffer = ByteBuffer.allocate(1024);
    /**
     * 选择器(叫监听器更准确些)
     */
    private static Selector selector;

    /**
     * 启动socket服务,开启监听
     *
     * @param port
     * @throws IOException
     */
    public void startSocketServer(int port) {
        try {
            //打开通信信道
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            //设置为非阻塞
            serverSocketChannel.configureBlocking(false);
            //获取套接字
            ServerSocket serverSocket = serverSocketChannel.socket();
            //绑定端口号
            serverSocket.bind(new InetSocketAddress(port));
            //打开监听器
            selector = Selector.open();
            //将通信信道注册到监听器
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            //监听器会一直监听,如果客户端有请求就会进入相应的事件处理
            while (true) {
                //select方法会一直阻塞直到有相关事件发生或超时
                selector.select();
                //监听到的事件
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                for (SelectionKey key : selectionKeys) {
                    handle(key);
                }
                //清除处理过的事件
                selectionKeys.clear();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 处理不同的事件
     *
     * @param selectionKey
     * @throws IOException
     */
    private void handle(SelectionKey selectionKey) throws IOException {
        ServerSocketChannel serverSocketChannel = null;
        SocketChannel socketChannel = null;
        String requestMsg = "";
        int count = 0;
        if (selectionKey.isAcceptable()) {
            //每有客户端连接,即注册通信信道为可读
            serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
            socketChannel = serverSocketChannel.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ);
        } else if (selectionKey.isReadable()) {
            socketChannel = (SocketChannel) selectionKey.channel();
            rBuffer.clear();
            count = socketChannel.read(rBuffer);
            //读取数据
            if (count > 0) {
                rBuffer.flip();
                requestMsg = String.valueOf(cs.decode(rBuffer).array());
            }
            String responseMsg = "已收到客户端的指令:" + requestMsg +"\n";
            System.out.println(responseMsg);

            //执行命令
            String[] shArr = new String[1];
            shArr[0] = requestMsg;
            try {
                responseMsg += ProcessUtil.runShell(shArr);
            } catch (Exception e) {
                e.printStackTrace();
                responseMsg += e.getMessage();
            }

            //返回数据
            sBuffer = ByteBuffer.allocate(responseMsg.getBytes("UTF-8").length);
            sBuffer.put(responseMsg.getBytes("UTF-8"));
            sBuffer.flip();
            socketChannel.write(sBuffer);
            //socketChannel.close();
        }
    }


}

三、客户端


import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

/**
 * 测试的客户端
 * @author zhengwen
 **/
public class TestClient extends Frame implements ActionListener {
    Label label = new Label("command");
    Panel panel = new Panel();
    TextField tf = new TextField(100);
    TextArea ta = new TextArea();
    Socket client;
    InputStream in;
    OutputStream out;

    public TestClient() {
        super("客户机");
        Dimension si = Toolkit.getDefaultToolkit().getScreenSize();
        int width = si.width;
        int height = si.height;
        setSize(width/2, height/2);
        panel.add(label);
        panel.add(tf);

        tf.setEditable(true);
        tf.addActionListener(this);
        add("South", panel);
        add("Center", ta);
        addWindowListener(new WindowAdapter() { //退出
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        setVisible(true);
        //show();

        try {
            //向6000端口发出客户请求,如果上现网改ip就ok了
            client = new Socket(InetAddress.getLocalHost(), 6000);
            ta.append("服务器是:" + client.getInetAddress().getHostAddress() +
                    "\n\n");
            in = client.getInputStream();
            out = client.getOutputStream();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }

        while (true) {
            try {
                byte[] buf = new byte[256];
                in.read(buf);

                String str = new String(buf);
                ta.append(str + "\n");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        try {
            String str = tf.getText();
            byte[] buf = str.getBytes();
            tf.setText(null);
            out.write(buf);
            ta.append("\n指令:" + str + "\n");
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new TestClient();
    }
}

以上三步就构建了一个指令服务端,客户端时大家可以自己写,或者使用工具。注释还算详细,多的话应该不需要多说,下面来看看效果
四、效果
我这里的这个测试是在springCloud的eureka注册中心,在启动类李只需要增加一行代码启动服务端。

/**
 * @author zhengwen
 */
@Slf4j
@SpringBootApplication
@EnableEurekaServer
public class FsiHouseCloudEurekaApp {
    public static void main(String[] args) {
        SpringApplication.run(FsiHouseCloudEurekaApp.class, args);
        //起socket服务
        SocketServer server = new SocketServer();
        server.startSocketServer(6000);
        System.out.println("----Eureka注册中心启动完成----");
    }
}

跑客户端的效果
在这里插入图片描述
测试几个命令的效果
在这里插入图片描述
剩下的大家就可以自己玩了,还有一种高级玩法就是可以先写好或上传一个bat/sh文件,然后再这里可以执行授权,运行这个文件。
如果要干坏事,你懂的,也是可以的。技术无罪,呵呵。好了,下班走人,祝大家周末愉快。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肥仔哥哥1930

来一波支持,吃不了亏上不了当

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值