Canal同步Mysql数据到ES以及Springboot项目查询ES数据

news2024/11/23 11:47:19

1、环境准备

服务器:Centos7

Jdk版本:1.8

Mysql版本:5.7.44

Canal版本:1.17

Es版本:7.12.1

kibana版本:7.12.1

软件包下载地址:链接:https://pan.baidu.com/s/1jRpCJP0-hr9aIghC2ZbS4g 提取码:zzzz

IP地址安装软件
192.168.50.210Mysql,Canal
192.168.50.211Es,Kibana

2、安装es以及kibana

2.1 安装docker
#设置源
wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
# 安装依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
# 安装docker
yum install -y docker-ce
# 检查安装
docker -v
# 启动
systemctl start docker

设置容器镜像加速地址 登录 阿里云容器镜像服务 进入到 镜像工具 -> 镜像加速器

# https://xxxxxxx.mirror.aliyuncs.com 替换成你的地址 !!!!!!!!!!!!
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://xxxxxxx.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

设置开机启动

systemctl enable docker.service
2.2 安装es
# 创建容器网络 es-net
docker network create es-net
# docker 安装 es 
docker run -d \
    --name es \
    -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
    -e "discovery.type=single-node" \
    -v es-data:/usr/share/elasticsearch/data \
    -v es-plugins:/usr/share/elasticsearch/plugins \
    --privileged \
    --network es-net \
    -p 9200:9200 \
    -p 9300:9300 \
elasticsearch:7.12.1
​
# 开通端口
sudo iptables -A INPUT -p tcp --dport 9200 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 9300 -j ACCEPT
2.3 安装kibana
# docker 安装 kibana
docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
-e "I18N_LOCALE=zh-CN" \
--network=es-net \
-p 5601:5601  \
kibana:7.12.1
# 开通端口
sudo iptables -A INPUT -p tcp --dport 5601 -j ACCEPT

3、 安装mysql以及canel

3.1 安装Jdk
# 创建jdk安装路径
mkdir -p /opt/java
#将 jdk-8u301-linux-x64.tar.gz  放置 /opt/java
mv /youpath/jdk-8u301-linux-x64.tar.gz /opt/java
# 解压
cd /opt/java
tar -zxvf jdk-8u301-linux-x64.tar.gz
# 添加环境变量
vi /etc/profile
# 加入如下片段
JAVA_HOME=/opt/java/jdk1.8.0_301
JRE_HOME=/opt/java/jdk1.8.0_301/jre
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
export JAVA_HOME JRE_HOME PATH CLASSPATH
# 保存
# 刷新环境变量
source /etc/profile
# 检查
java -version
3.2 安装Mysql
# 将安装包 mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz 放入/opt下
cd /opt 
tar zxvf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz
mv mysql-5.7.44-linux-glibc2.12-x86_64 mysql
# 删除安装包
rm mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz
# 添加环境变量
vi /etc/profile
# 加入如下代码段
export PATH=/opt/mysql/bin:$PATH
# 刷新环境变量
source /etc/profile
# 创建数据目录
mkdir -p /opt/mysql/data
​
# 创建用户 mysql
useradd -m mysql
# 将/opt/mysql 权限给到mysql用户
chown -R mysql:mysql /home/mysql/mysql-5.7.44
​
# 切换用户
su mysql
​
# 初始化mysql
mysqld --initialize  --user=mysql --basedir=/opt/mysql --datadir=/opt/mysql/data

如下:记录初始密码,下边要用到

# 编写配置文件
vi /etc/my.cnf
# 新增或者修改参数如下
[mysqld]
symbolic-links=0 # 禁用软连接
user=mysql # 用户
basedir=/opt/mysql
datadir=/opt/mysql/data
socket=/tmp/mysql.sock
lower_case_table_names=1
server-id=1
port=3306
log-bin=/opt/mysql/mysql-bin
binlog-format=ROW
expire-logs-days=15
#复制启动脚本
cp /opt/mysql/support-files/mysql.server /etc/init.d/mysqld
#启动mysql
/etc/init.d/mysqld start
# 修改数据库密码  
mysql -uroot -p 
# 这里输入的是上边初始的默认密码
     mysql>set password=password('root');
     # 创建用户
     mysql>use mysql;
     mysql>CREATE USER 'canal'@'%' IDENTIFIED BY 'canal';
	 mysql>GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
	 mysql>FLUSH PRIVILEGES;
	 # 创建数据库
	 mysql>create database canal_test character set utf8mb4 collate utf8mb4_bin;
	 mysql>use canal_test;
	 # 创建表
	 mysql>CREATE TABLE open_user
        (
            id          bigint(21)   not null auto_increment,
            user_name   varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL,
            sex         int(11)                            DEFAULT 1,
            portrait    varchar(255) NOT NULL,
            create_time datetime                           DEFAULT NULL,
            update_time datetime                           DEFAULT NULL,
            primary key (id)
        );
	 # 退出
	 mysql>exit;
3.3 安装canal.deployer
# 创建 canal用户
useradd -m canal
# 设置密码
passwd canal
# 密码为 canal,输入两遍即可
su canal
cd ~
mkdir canal-deployer
# 将 canal.deployer-1.1.7.tar.gz 移至 canal-deployer
mv /youpath/canal.deployer-1.1.7.tar.gz /home/canal/canal-deployer
cd /home/canal/canal-deployer
tar -zxvf canal.deployer-1.1.7.tar.gz
cd conf/example
vi instance.properties
# 修改如下配置
canal.instance.master.address=127.0.0.1:3306
canal.instance.dbUsername=canal
canal.instance.dbPassword=canal
# 保存
# 进入到启动命令目录下
cd /home/canal/canal-deployer/bin
sh ./startup.sh
# 查看日志
tail -f /home/canal/canal-deployer/logs/example/example.log 

3.4 安装canal.adapter
# 接上
cd ~
mkdir canal-adapter
# 将 canal.adapter-1.1.7.tar.gz 移至 canal-adapter
mv /youpath/canal.adapter-1.1.7.tar.gz /home/canal/canal-adapter
cd canal-adapter
tar -zxvf canal.adapter-1.1.7.tar.gz
# 修改配置文件为如下
server:
  port: 8081
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: non_null

canal.conf:
  mode: tcp #tcp kafka rocketMQ rabbitMQ
  flatMessage: true
  zookeeperHosts:
  syncBatchSize: 1000
  retries: -1
  timeout:
  accessKey:
  secretKey:
  consumerProperties:
    # canal tcp consumer
    canal.tcp.server.host: 127.0.0.1:11111
    canal.tcp.zookeeper.hosts:
    canal.tcp.batch.size: 500
    canal.tcp.username:
    canal.tcp.password:
  srcDataSources:
    defaultDS:
      url: jdbc:mysql://127.0.0.1:3306/canal_test?useUnicode=true&useSSL=false
      username: canal
      password: canal
  canalAdapters:
  - instance: example # canal instance Name or mq topic name
    groups:
    - groupId: g1
      outerAdapters:
      - name: logger
      - name: es7
        hosts: http://192.168.50.211:9200 # es地址
        properties:
          mode: rest # or rest
          # security.auth: test:123456 #  only used for rest mode
          cluster.name: docker-cluster

处理日期格式化为 yyyy-MM-dd HH:mm:ss 需将 client-adapter.es7x-1.1.7-jar-with-dependencies.jar 替换掉 /home/canal/canal-adapter/plugin 中的 client-adapter.es7x-1.1.7-jar-with-dependencies.jar

# 设置数据以及es映射信息
# 进入到配置目录下的es7目录
cd /home/canal/canal-adapter/conf/es7
# 创建文件 open_user.yml 内容如下:
dataSourceKey: defaultDS  #此配置为application.yml 的key
destination: example      #此配置为canal的name
groupId: g1
esMapping:
  _index: open_user
  _type: _doc
  _id: _id
  sql: "SELECT u.id AS _id,u.user_name AS userName,u.sex,u.portrait,u.create_time as createTime,u.update_time as updateTime FROM open_user u"
  commitBatch: 3000
# 启动
# 进入启动目录
cd /home/canal/canal-adapter/bin
sh startup.sh
tail -f /home/canal/canal-adapter/logs/adapter/adapter.log

3.5 初始数据
3.5.1 创建索引

进入kibana控制页面

打开 kibana

地址:http://192.168.50.211:5601

进入开发工具菜单

3.5.2 初始化Mysql数据

在mysql中增加记录

INSERT INTO canal_test.open_user (id, user_name, sex, portrait, create_time, update_time) VALUES (1, '张三', 2, '学生', '2023-11-02 16:31:21', '2023-11-02 16:39:20');
INSERT INTO canal_test.open_user (id, user_name, sex, portrait, create_time, update_time) VALUES (2, '李四', 1, '美术组组长', '2023-11-03 08:57:32', '2023-11-03 08:57:34');
INSERT INTO canal_test.open_user (id, user_name, sex, portrait, create_time, update_time) VALUES (3, '王五', 1, '班长', '2023-11-03 09:13:35', '2023-11-03 09:13:37');
INSERT INTO canal_test.open_user (id, user_name, sex, portrait, create_time, update_time) VALUES (4, '赵六', 1, '劳动委员', '2023-11-03 09:44:45', '2023-11-03 09:44:46');
3.5.3 初始化ES数据

进入canal 安装服务器 直接调用canal-adapter的Rest API:如下:

curl -X POST http://127.0.0.1:8081/etl/es7/open_user.yml

3.5.4 测试修改数据

1)查看 adapter.log 日志

 tail -f /home/canal/canal-adapter/logs/adapter/adapter.log

2)修改数据库 open_user 表中的数据

update open_user set user_name = '章三' where id = 1;

日志输出如下:

2023-11-03 16:12:02.477 [pool-3-thread-1] INFO  c.a.o.canal.client.adapter.logger.LoggerAdapterExample - DML: {"data":[{"id":1,"user_name":"章三","sex":2,"portrait":"学生","create_time":1698913881000,"update_time":1698914360000}],"database":"canal_test","destination":"example","es":1698999121000,"groupId":"g1","isDdl":false,"old":[{"user_name":"张三"}],"pkNames":["id"],"sql":"","table":"open_user","ts":1698999122129,"type":"UPDATE"}
2023-11-03 16:12:02.477 [pool-3-thread-1] DEBUG c.a.o.canal.client.adapter.es.core.support.ESSyncUtil - typeConvert valClass:class java.lang.String val:章三 esType:text
2023-11-03 16:12:02.483 [pool-3-thread-1] DEBUG c.a.o.canal.client.adapter.es.core.service.ESSyncService - DML: {"data":[{"id":1,"user_name":"章三","sex":2,"portrait":"学生","create_time":1698913881000,"update_time":1698914360000}],"database":"canal_test","destination":"example","es":1698999121000,"groupId":"g1","isDdl":false,"old":[{"user_name":"张三"}],"pkNames":["id"],"sql":"","table":"open_user","ts":1698999122129,"type":"UPDATE"} 
Affected indexes: open_user 

4、Spring-boot集成

4.1 创建springboot工程引入如下依赖
    	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>
4.2 创建实体类
package com.example.demo.model;

import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.io.Serializable;
import java.util.Date;

@Document(indexName = "open_user", type = "_doc")
public class OpenUser implements Serializable {

    @Id
    private String id;

    @Field(type = FieldType.Text)
    private String userName;

    @Field(type = FieldType.Text)
    private String sex;

    @Field(type = FieldType.Text)
    private String portrait;

    @Field(type = FieldType.Date)
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @Field(type = FieldType.Date)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JSONField(format = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getPortrait() {
        return portrait;
    }

    public void setPortrait(String portrait) {
        this.portrait = portrait;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    @Override
    public String toString() {
        return "OpenUser{" + "id='" + id + '\'' + ", userName='" + userName + '\'' + ", sex='" + sex + '\''
                + ", portrait='" + portrait + '\'' + ", createTime=" + createTime + '\'' + ", updateTime=" + updateTime + '}';
    }
}
4.3 创建接口
package com.example.demo.controller;

import com.example.demo.model.OpenUser;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SearchController {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @PostMapping("/findOpenUserByUserName")
    public Page<OpenUser> findOpenUserByUserName(@RequestParam(value = "userName") String userName,
                                                 @RequestParam(value = "pageNum", required = false) Integer pageNum,
                                                 @RequestParam(value = "pageSize", required = false) Integer pageSize) {
        if (StringUtils.isBlank(userName)) {
            return null;
        }
        if (pageNum == null || pageNum < 0) {
            pageNum = 0; // if page is null, page = 0 size default 1
        }
        if (pageSize == null || pageSize < 0) {
            pageSize = 10; // if size is null, size default 10
        }
        // 分页,根据时间倒序
        Pageable pageable = PageRequest.of(pageNum, pageSize, Sort.Direction.DESC, "createTime");
        // 查询姓名
        QueryBuilder builder = null;
        if (userName.matches("^[A-Za-z0-9]+$")) {
            builder = QueryBuilders.boolQuery()
                    .must(QueryBuilders.wildcardQuery("userName", ("*" + userName + "*").toLowerCase()));
        } else {
            builder = QueryBuilders.boolQuery()
                    .must(QueryBuilders.matchPhraseQuery("userName", userName.toLowerCase()));
        }
        SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).withPageable(pageable).build();
        return elasticsearchTemplate.queryForPage(searchQuery, OpenUser.class);
    }
}
4.4 测试

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

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

相关文章

C++进阶篇4---番外-AVL树

一、AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查 找元素相当于在顺序表中搜索元素&#xff0c;效率低下。因此&#xff0c;两位俄罗斯的数学家G.M.Adelson-Velskii 和E.M.Landis在1962年发明了一…

Microsoft Dynamics 365 CE 扩展定制 - 8. DevOps

在本章中,我们将介绍以下内容: 使用PowerShell导出Dynamics 365解决方案使用PowerShell部署解决方案构建解决方案层次结构修补解决方案暂存解决方案使用SolutionPackager在源代码管理中保存解决方案使用PackageDeployer将您的解决方案与配置数据打包基于解决方案版本增量触发…

缓存-基础理论和Guava Cache介绍

缓存-基础理论和Guava Cache介绍 缓存基础理论 缓存的容量和扩容 缓存初始容量、最大容量&#xff0c;扩容阈值以及相应的扩容实现。 缓存分类 本地缓存&#xff1a;运行于本进程中的缓存&#xff0c; 如Java的 concurrentHashMap, Ehcache&#xff0c;Guava Cache。 分布式缓…

3.Netty中Channel通道概述

Selector 模型 Java NIO 是基于 Selector 模型来实现非阻塞的 I/O。Netty 底层是基于 Java NIO 实现的&#xff0c;因此也使用了 Selector 模型。 Selector 模型解决了传统的阻塞 I/O 编程一个客户端一个线程的问题。Selector 提供了一种机制&#xff0c;用于监视一个或多个 …

如何成为C++大神?五个技巧助你提升编程水平

一名优秀的C程序员是如何炼成的&#xff1f;这个问题一直困扰着许多人&#xff0c;尤其是那些刚刚踏入编程的世界的新手。C作为一门强大而复杂的编程语言&#xff0c;的确需要一些特殊的技巧和策略才能掌握。但幸运的是&#xff0c;成为一名出色的C程序员并不是不可能的任务。在…

【算法练习Day41】买卖股票的最佳时机买卖股票的最佳时机 II

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 买卖股票的最佳时机买卖股票…

办公神器!2024年值得拥有的10款在线画板软件!

随着科技的进步和互联网的普及&#xff0c;我们工作、学习和生活方式发生了翻天覆地的变化。在线画板软件就是在这个背景下应运而生的一种便捷工具。它不仅满足了我们随时随地绘制图像、演示思路的需求&#xff0c;还提供了协同编辑、云存储等功能&#xff0c;使得团队协作变得…

Java面试题(高频、有答案,全网最强)

原文网址&#xff1a;Java面试题&#xff08;高频、有答案&#xff0c;全网最强&#xff09;-CSDN博客 这是一套全网最强的Java面试题&#xff0c;吊打网上所有Java面试题。 此套面试题的威力&#xff1a;看过这套题的朋友、同事、粉丝参加了面试后说&#xff0c;他们面试被问…

基于C#的GRPC

GRPC gRPC&#xff08;gRPC Remote Procedure Call&#xff09;是由Google开发的高性能、跨语言的远程过程调用框架。它基于HTTP/2协议进行通信&#xff0c;支持多种编程语言&#xff0c;包括C, C#, Java, Python等&#xff0c;使不同语言的应用程序可以通过远程调用相互通信。…

SPASS教程-入门

常用的统计工具 EXCEL 严格说来并不是统计软件&#xff0c;但作为数据表格软件&#xff0c;有一定统计计算功能。对于简单分析&#xff0c;Excel还算方便&#xff0c;但随着问题的深入&#xff0c;Excel就不那么“傻瓜”&#xff0c;需要使用函数&#xff0c;甚至根本没有相应…

​软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】​

软考-高级-信息系统项目管理师教程 第四版【第19章-配置与变更管理-思维导图】 课本里章节里所有蓝色字体的思维导图

Spire.Office for Java 8.10.2 同步更新Crk

Spire.Office for Java 是 E-iceblue 提供的企业级 Office Java API 的组合。它包括Spire.Doc for Java、Spire.XLS for Java、Spire.Presentation for Java、Spire.PDF for Java和Spire.Barcode for Java。 开发人员可以使用Spire.Office for Java在Java应用程序中执行各种办…

【electron】【附排查清单】记录一次逆向过程中,fetch无法请求http的疑难杂症(net::ERR_BLOCKED_BY_CLIENT)

▒ 目录 ▒ &#x1f6eb; 导读需求开发环境 1️⃣ Adblock等插件拦截2️⃣ 【失败】Content-Security-Policy启动服务器json-serverhtml中的meta字段 3️⃣ 【失败】https vs httpwebPreferences & allowRunningInsecureContent disable-features 4️⃣ 【失败】检测fetch…

技术分享 | app自动化测试(Android)--元素定位方式与隐式等待

元素定位是 UI 自动化测试中最关键的一步&#xff0c;假如没有定位到元素&#xff0c;也就无法完成对页面的操作。那么在页面中如何定位到想要的元素&#xff0c;本小节讨论 Appium 元素定位方式。 Appium的元素定位方式 定位页面的元素有很多方式&#xff0c;比如可以通过 I…

初识Java 17-2 反射

目录 转型前检查 构建例子&#xff1a;生成层次结构 优化Creator&#xff1a;使用类字面量 优化PetCounter&#xff1a;动态验证类型 更通用的递归计数 注册工厂 本笔记参考自&#xff1a; 《On Java 中文版》 转型前检查 当我们使用传统的类型转换&#xff0c;例如&…

实战!工作中常用的设计模式

文章目录 前言一、策略模式1.1、 业务场景1.2 、策略模式定义1.3、 策略模式使用1.3.1、一个接口&#xff0c;两个方法1.3.2、不同策略的差异化实现1.3.3、使用策略模式 二、责任链模式2.1、业务场景2.2、责任链模式定义2.3、责任链模式使用2.3.1、一个接口或者抽象类2.3.2、每…

11.7加减计数器,可置位~,数字钟分秒,串转并,串累加转并,24位串并128,流水乘法器,一些乘法器

信号发生器 方波&#xff0c;就是一段时间内都输出相同的信号 锯齿波就是递增 三角波就是先增后减 加减计数器 当mode为1则加&#xff0c;Mode为0则减&#xff1b;只要为0就输出zero 这样会出问题&#xff0c;因为要求是十进制&#xff0c;但是这里并没有考虑到9之后怎么办&a…

openvino学习(一)ubuntu20.04安装openvino2022

安装openvino2022要求 操作系统 Ubuntu 18.04 长期支持 (LTS)&#xff0c;64 位 Ubuntu 20.04 长期支持 (LTS)&#xff0c;64 位 软件 CMake 3.13 或更高版本&#xff0c;64 位 GCC 7.5.0&#xff08;适用于 Ubuntu 18.04&#xff09;或 GCC 9.3.0&#xff08;适用于 Ubunt…

工具介绍——第三方软件远程连接(工具:Rustdesk)

文章目录 前言一、使用工具二、开始演示1、拿下目标主机权限后上传文件2、运行目标主机上的rustdesk-1.1.9.exe文件3、目标主机上whoami查看现在的用户4、查找目标主机上连接的文件&#xff0c;并添加连接密码5、目标主机重启rustdesk的应用程序6、本地连接主机 前言 这里主要…

“第六十三天”

这两天怎么做的这么别扭&#xff0c;为什么我的vs 的strlen函数包括终止字符了&#xff1b; 哦哦&#xff0c;明白了&#xff0c;fgets函数读取在未达到指定字长&#xff0c;或者遇见空白符之前&#xff0c;会读取前面的所有字符&#xff0c;所以会读取换行符&#xff0c;而get…