Jenkins+kubernetes流水线构建java项目

        在传统的业务环境中,我们的应用部署或者更新都是采用手工的方式,但是在企业内部,应用架构一般都采用微服务,大部分项目都会对应几十个、上百甚至上千个微服务,并且还不仅仅只有一个项目,所以采用收工方式上线是不太现实的事情,特别是随着应用的增多,对应的工作量也变得不可想象。由于上线的过程一般比较固定,大都是提前规定好、比较一致的流程,因此采用工具来完成这类“死板”的工作时比较推荐的方式,同时也能减少手工操作所带来的故障风险。
        本章主要介绍在生产环境中持续集成(Continuous Integration,CI)与持续部署(ContinuousDeployment,CD)的使用,实现Jenkins 流水线脚本自动发布应用到 Kubernetes 集群中,当然 CI/CD是 Devops 中非常重要的一个环节。

一、CI/CD 介绍

        CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法。CI/CD 的核心概念是持续集成、持续交付(Continuous Delivery,CD)和持续部署。作为一个面向开发和运营团队 的解决方案,CI/CD 主要针对在集成新代码时所引发的问题(也称“集成地狱”)。
        具体而言,CI/CD 在整个应用生命周期内,(从集成和测试阶段到交付和部署)引入了持续自动化和持续监控,这些关联的事物通常被称为“CI/CD 管道”,由开发和运维团队以敏捷方式协同支持。

1.持续集成(CI)

        现代应用开发的目标是让多位开发人员同时开发同一个应用的不同功能。但是,如果企业安排在一天内将所有分支源代码合并在一起,最终可能导致工作烦琐、耗时,而且需要手动完成。这是因为当一位独立工作的开发人员对应用进行更改时,有可能会有其他开发人员同时进行更改,从而引发冲突。

        持续集成可以帮助开发人员更加频繁地将代码更改合并到共享分支或主干中。一旦开发人员对应用所做的更改被合并,系统就会通过自动构建应用并运行不同级别的自动化测试(通常是单元测试和集成测试)来验证这些更改,确保更改没有对应用造成破坏。这意味着测试内容涵盖了从类和函数到构成整个应用的不同模块,如果自动化测试发现新代码和现有代码之间有冲突,持续集成可以更加轻松快速地修复这些错误。

2.持续交付(CD)

        完成持续集成中构建单元测试和集成测试的自动化流程后,通过持续交付可以自动将已验证的代码发布到存储库。为了实现高效的持续交付流程务必要确保持续交付已内置于开发管道。持续交付的目标是拥有一个可随时部署到生产环境的代码库。
        在持续交付中,每个阶段(从代码更改的合并到生产就绪型构建版本的交付)都涉及测试自动化和代码发布自动化。在流程结束时,运维团队可以快速、轻松地将应用部署到生产环境中。

3.持续部署(CD)

        对于一个成熟的 CI/CD 管道来说,最后的阶段是持续部署。作为持续交付(自动将生产就绪型构建版本发布到代码存储库)的延伸,持续部署可以自动将应用发布到生产环境中。由于生产之前的管道阶段没有手动门控,因此持续部署在很大程度上都得依赖精心设计的测试自动化。
        实际上,持续部署意味着开发人员对应用的更改在编写后的几分钟内就能生效,这更加便于持续接收和整合用户反馈。总而言之,所有这些 CI/CD 的关联步骤都有助于降低应用的部署风险因此更便于以小件的方式(非一次性)发布对应用的更改。不过,由于还需要编写自动化测试以适应 CI/CD 管道中的各种测试和发布阶段,因此前期投资会很大。

4.CI 和 CD 的区别

        CI/CD 中的 CI 即持续集成,它属于开发人员的自动化流程。成功的 CI 意味着应用代码的最新更改会定期构建、测试并合并到共享存储中。该解决方案可以解决在一次开发中有太多应用分支,从而导致相互冲突的问题。CI/CD 中的 CD诣的是持续交付或持续部署,这些相关概念有时会交叉使用。两者都事关管道后续阶段的自动化,但它们有时也会单独使用,用于说明自动化程度。
        持续交付通常是指开发人员对应用的更改会自动进行错误测试并上传到存储库(如 Gitlab 或容器注册表),然后由运维团队将其部署到实时生产环境中,旨在解决开发和运维团队之间可见性及沟通较差的问题,因此持续交付的目的就是确保尽可能减少部署新代码时所需的工作量。
        持续部署指的是自动将开发人员的更改从代码库发布到生产环境中以供客户使用,它主要为解决因手动流程降低应用交付速度,从而使运维团队超负荷的问题。持续部署以持续交付的优势为根基,实现了管道后续阶段的自动化。
        CI/CD 既可能仅指持续集成和持续交付构成的关联环节,也可以指持续集成、持续交付和持续部署这 3个方面构成的关联环节。更为复杂的是有时持续交付也包含持续部署流程。
        纠缠于这些语义其实没有必要,只需记得 CI/CD 实际上就是一个流程(通常表述为管道),用于在更大程度上实现应用开发的持续自动化和持续监控。

二、项目环境

1.项目介绍

        kubernetes 目前是最为流行的应用运行环境,应用以容器的形态运行在平台之上,可以实现一些动态的策略,保证服务的 SLA。因此 Devops 也必须适应这种新形态应用的部署的方式。而对 Devops 来讲其实容器化的出现以及容器平台的出现,其实让 DevOps 更为简单了。在使用 Jenkins kubernetes 插件的时候,你就会对流水线的认知更加深刻。

        总结起来具有以下优势:

  • 容器化平台的动态创建 slave 的方式节约了系统的资源,构建结束后可自行销毁。
  • 容器化配置同一流水线的不同的步骤运行环境,且在一定程度上实现隔离。
  • kubernetes Pod 的多容器共享 volume 的机制,让各个流水线共享操作的中间产物。
  • 模块化的配置流水线的方式,可以对流水线不同版本的工具进行统一的配置管理。

        传统的 kubernetes 的操作方式是在一个环境下配置所有的工具,导致对 Jenkins master/slave的环境配置要求较大。而到了容器的平台之上,不同的环境的操作可以天然的隔离到不同的容器之中,而且可以像搭积木一样实现流水线分工,还能通过存储共享的方案实现互相之间中间产物的传递,可以说真正的将流水线的设计提现的淋漓尽致。

2.设备清单

三、安装流水线环境

1.安装kubernetes集群

2.安装jenkins

本案例账号密码

admin

admin

3.安装Gitlab

本案例账号密码

root

pwd12345

4.安装Harbor

本案例账号密码

admin

Harbor12345

四、添加凭据

        在使用 Jenkins、GitLab、Harbor、Kubemetes 打造 DcvOps 平台实现 CI/CD 时,需要涉及很多证书、账号和密码、公钥和私钥的配置,这些凭证需要放在一个统一的地方管理,并且.能在整个流水线中使用,而 Jenkms 提供的 Credentials 插件可以满足以上要求,并且在流水线中也不会泄露相关的加密信息。所以 Harbor 的账号和密码、GltLab 的私钥、Kubernetes的证书均使用,Jenkins 的 Credentials 管理。

1.添加Kubernetes 证书

        在安装和维护 Kubernetes 集群时,都是使用 kubect1 操作集群,而 kubect1 操作集群需要-个KUBECONFIG 文件,我们使用 Jenkins 控制 Kubernetes 时,也是使用该文件,所以该文件需要放置在Credentials 中,之后可以被 Jenkins 的 Kubernetes 插件使用。首先需要找到集群中的 KUBECONFIG,一般是 kubectl 节点的~/.kube/confg 文件,或者是 KUBECONFIG
环境变量所指向的文件,例如/etc/kubernetes/admin.conf 文件

(1)准备 config 文件

将 kubernetes 的 master 主机中 config 文件拷贝出来放到本地主机上。

(2)上传 config 文件

Dashboard-->Manage Jenkins-->Credentials

点击 system 的“全局”域,并添加凭据

 注意:
ID:study-k8s-kubeconfig

描述:k8s study 环境 kubeconfig

(3)用上一步中生成的凭据创建 kubernetes 连接

Dashboard-->Manage Jenkins-->Clouds-->Clouds, 点击“New cloud为kubernetes集群设置名称:kubernetes-study.

2.配置 Harbor 账号和密码 

(1)在 jenkins 中找到凭据项

Dashboard-->Manage Jenkins-->Credentials

(2)添加 Harbor 凭据

填写 harbor 用户的账号密码
本案例的账号密码为 admin 和 Harbor12345

设置 ID 为“HARBOR_ACCOUNT"

3.最后的所有凭据 

 4.配置Agent

(1)什么是 Agent

        Jenkins Agent 是 Jenkins 的一个插件,它的作用是跨平台地在分布式环境中构建和执行任务。它可以在不同的操作系统和架构上运行,并且可以由Jenkins Master 上的特定 Jenkins Job 来指定程序和参数,以便在 Agent 上执行。Jenkins Agent 可以在计算机上实时唤醒或远程连接来执行任务。

(2)Jenkins Agent 的作用
  • 分布式构建:分布式构建是指将一个单一任务分摊到多个计算机上执行,以提高构建速度和效率。Jenkins Agent 用于在不同的节点上分别执行单元测试、编译和构建部分、测试任务等。
  • 管理远程计算机:JenkinsAgent 可以远程连接到目标计算机,实现管理和监控远程计算机的功能。例如,可以使用 Agent 在远程计算机上执行命令、上传文件或下载日志等操作。
  • 自动化测试:Jenkins Agent 可以用于自动化测试环境中。例如,在 Android 应用测试中,可以使用 Jenkins Agent 在通过 Android 模拟器启动测试设备,然后执行自动化测试任务。
(3)添加代理

Dashboard-->Manage Jenkins-->Security

找到代理项,设置端口为 50000

备注:
        有了这个代理,在 kubernetes 上为节点做个标签(本案例的标签为“build=true”),之后的jenkinsfile 的 agent 就会根据这个标签创建 Pod。

五、自动化构建java项目

1.在 Harbor 中添加项目,名称为 kubernetes

2.所有的 docker 主机(包括 kubernetes 主机)设置 harbor 仓库

(1)设置各个主机的 私有仓库
cat /etc/docker/daemon.json 
{
"exec-opts":["native.cgroupdriver=systemd"],
"registry-mirrors":["https://cf-workers-docker-io-8jv.pages.dev"],
"insecure-registries":["192.168.10.106"]
}
(2)重启 docker 进程 
systemctl daemon-reload
systemctl restart docker
(3)测试私有仓库 
docker tag centos:7 192.168.10.106/kubernetes/centos:7
docker login -u admin -p Harbor12345 http://192.168.10.106docker push 192.168.10.106/kubernetes/centos:7

 3.创建 java 测试用例

在 gitlab 中添加项目
项目来自 https://gitee.com
https://gitee.com/kgc-wjq/spring-boot-project.git

 4.定义jenkinsfile

        jenkinsfile 定义流水线的步骤包括拉取代码、执行构建、生成镜像、更新 Kubernetes 资源等。本案例将 jenkinsfile 放置于项目源代码一并管理,也可以单独放置于一个 Git 仓库进行管理。
        接下来在 GitLab 的源代码中添加 jenkinsfile。首先单击代码首页的“十’,然后单击 Upload file上传编辑好的文件,文件名字为 Jenkinsfile文件内容参考本文件附件 Jenkins

5.编写dockerfile

        接下来在 GitLab 的源代码中添加 Dockerfile。首先单击代码首页的“十’,然后单击 Upload file上传编辑好的文件,文件名字为 Dockerfile,Dockerfile 需要和 Jenkinsfile 在同一级目录下。该dockerfile 用来创建一个 java 的镜像,并且在该镜像中放置构建好的 maven 项目的 jar 包。

Dockerfile 的内容如下:

 6.定义 kubernetes 资源

(1)在kubernetes 中为 node1 做标签
[root@master ~]# ku label node node1 build=true
node/node1 labeled

备注:
为 agent Pod 调度到指定的节点 

(2)创建命名空间
[root@master ~]# ku create namespace kubernetes
namespace/kubernetes created
(3)创建 secret 保存 harbor 的认证信息 
[root@master ~]# ku create secret docker-registry harborkey --docker-server=192.168.10.106 --docker-username=admin --docker-password=Harbor12345 --docker-email=3315715079@qq.com -n kubernetes
secret/harborkey created
 (4)编写应用的Deployment

这里创建一个 nginx 的应用程序,用来运行 spring-boot 项目

[root@master ~]# cat spring-boot-project.yaml 
---
apiVersion: v1
kind: Service
metadata:
  creationTimestamp: null
  labels:
    app: spring-boot-project
  name: spring-boot-project
  namespace: kubernetes
spec:
  ports:
  - name: web
    port: 8761
    protocol: TCP
    targetPort: 8761
  selector:
    app: spring-boot-project
  sessionAffinity: None
  type: NodePort
status:
  loadBalancer: {}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  creationTimestamp: null
  name: spring-boot-project
  namespace: kubernetes
spec:
  rules:
  - host: spring-boot-project.test.com
    http:
      paths:
      - backend:
          service:
            name: spring-boot-project
            port: 
              number: 8761
        path: /
        pathType: ImplementationSpecific
status:
  loadBalancer: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: spring-boot-project
  name: spring-boot-project
  namespace: kubernetes
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-boot-project
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: spring-boot-project
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - spring-boot-project
              topologyKey: kubernetes.io/hostname
            weight: 100
      containers:
      - env:
        - name: TZ
          value: Asia/Shanghai
        - name: LANG
          value: C.UTF-8
        image: nginx:1.7.9
        imagePullPolicy: IfNotPresent
        lifecycle: {}
        name: spring-boot-project
        ports:
        - containerPort: 8761
          name: web
          protocol: TCP
        resources:
          limits:
            cpu: 994m
            memory: 1170Mi
          requests:
            cpu: 10m
            memory: 55Mi
      dnsPolicy: ClusterFirst
      imagePullSecrets:
      - name: harborkey
      restartPolicy: Always
      securityContext: {}
      serviceAccountName: default
 (5)创建该资源(该资源会调度到 node01 或 node02)
[root@master ~]# ku create -f spring-boot-project.yaml 
service/spring-boot-project created
ingress.networking.k8s.io/spring-boot-project created
deployment.apps/spring-boot-project created
[root@master ~]# ku get pod -n kubernetes
NAME                                   READY   STATUS              RESTARTS   AGE
spring-boot-project-6656bb496b-klcxg   0/1     ContainerCreating   0          2s

7.创建 jenkins 任务 

(1)新建 Item

项目名称:spring-boot-project
项目类型:Pipline

(2)创建一个 SCM 项目

在 Pipline(流水线)区域输入 Git 仓库地址,分支为 master,保存

 (3)单击 Build Now 开始构建

注意:
        创建完成后,单击 Build Now(由于 Jenkins 参数由 Jenkinsfile 生成,因此第一次执行流水线会失败),第一次构建结束后,可以看到 Build Now变成了 Build with Parameters。单击 Build withParameters 后,可以读取到 Git 仓库的分支,之后可以选择分支手动构建。

(4)查看svc
[root@master ~]# ku get svc -n kubernetes
NAME                  TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
spring-boot-project   NodePort   10.96.13.141   <none>        8761:30502/TCP   6m32s
(5)访问测试

http://192.168.10.101:31298/

8.设置 jenkins 的自动触发

(1)设置“构建触发器”

项目-->配置-->构建触发器,勾选项目的 webhook

(2)设置“构建触发器”的高级选项

(3)复制出token 值和 webhook URL

Token:
8e87a846cxXXXXXXX2d6505XXXXX


webhook URL:
http://192.168.10.104:8080/jenkins/project/spring-boot-project

9.设置 Gitlab 的触发机制

(1)找到 Admin 选项

单击 Menu-->Admin

(2)设置网络允许外发请求

Menu-->Admin-->Settings-->Network-->Outbound requests

(3)设置0utbound request

(4)设置项目的webhook 参数

打开自己创建的项目,Settings-->Webhooks
填写前面步骤中生成的 webhook 的 URL 和 Token
最后点击页面底部的 Add Webhook 按钮

(5)点击测试按钮测试

六、项目总结

        本节课提供了 Jenkins 在 kubernetes 环境中的使用方案,该方案是利用 Jenkins kubernetes 插件的方式运行流水线,并可以自己动态构建所需要的流水线运行环境。使用 wcredential 凭据管理的方式使用 Jenkins 凭据,减少敏感信息的明文存储。并可以使用 groovy 脚本配合声明式 pipline 配置来进行更加复杂的操作。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序开发-配置文件详解

文章目录 一&#xff0c;小程序创建的配置文件介绍二&#xff0c;配置文件-全局配置-pages 配置作用&#xff1a;注意事项&#xff1a;示例&#xff1a; 三&#xff0c;配置文件-全局配置-window 配置示例&#xff1a; 四&#xff0c;配置文件-全局配置-tabbar 配置核心作用&am…

【Linux】————进程控制

作者主页&#xff1a; 作者主页 本篇博客专栏&#xff1a;Linux专栏 创作时间 &#xff1a;2024年10月10日 ​ ​ 一、程序地址空间&#xff1a; 1、C/C中的程序地址空间&#xff1a; ​ 在c中我们了解了这样的空间分布图。 我们应如何去创建和访问变量呢&#xff1f;…

VR线上展厅:超越时空的沉浸式展览,打造个性化、高效展览新模式

一、沉浸式漫游&#xff1a;打破时空限制&#xff0c;尽享虚拟之旅 VR线上展厅通过高度逼真的3D场景构建&#xff0c;为参观者营造了一个仿佛置身其中的虚拟世界。借助各种显示设备&#xff0c;用户能够自由穿梭于各个展区之间&#xff0c;无论是漫步在历史悠久的博物馆&#…

双语大脑的神经可塑性能力:来自健康和病理个体的见解

摘要 双语经验的神经印记对于理解大脑如何处理优势语言和非优势语言至关重要&#xff0c;但关于它的研究仍然没有定论。不同的研究表明神经处理存在相似性或差异性&#xff0c;这对患有脑肿瘤的双语患者具有重要意义。保留术后的双语功能需要考虑到术前的神经可塑性变化。在这…

【论文阅读笔记】End-to-End Object Detection with Transformers

代码地址&#xff1a;https://github.com/facebookresearch/detr 论文小结 本文是Transformer结构应用于目标检测&#xff08;OD&#xff09;任务的开山之作。方法名DETE&#xff0c;取自Detection Transformer。   作为2020年的论文&#xff0c;其表现精度在当时也不算高的…

pytorch导入数据集

1、概念&#xff1a; Dataset&#xff1a;一种数据结构&#xff0c;存储数据及其标签 Dataloader&#xff1a;一种工具&#xff0c;可以将Dataset里的数据分批、打乱、批量加载并进行迭代等 &#xff08;方便模型训练和验证&#xff09; Dataset就像一个大书架&#xff0c;存…

mongodb GUI工具(NoSQLBooster)

介绍 跨平台的MongoDB GUI工具&#xff0c;支持Windows、macOS和Linux。自带服务器监控工具、Visual Explain Plan、查询构建器、SQL查询等功能。提供免费版本&#xff0c;但功能相比付费版本有所限制。 免费版可供个人/商业使用&#xff0c;但功能有限。 安装成功后&#x…

大疆M2006+C610 pid参数调优

官方给的示例代码里给的是1.5, 0.1, 0 但试了下空转时显然不太行. 自己摸索出0.8, 0.03, 0 表现如图中的蓝色线 期望速度先两秒的1000,然后一秒的2000,一秒的3000, 0 2000 表现还不错,可以看到0.5秒后与期望值的差距控制在大概10%之内,但还是感觉有些过调 对了先说一下基础知识…

有什么方法可以保护ppt文件不被随意修改呢?

在工作或学习中&#xff0c;我们常常需要制作powerpoint演示文稿&#xff0c;担心自己不小心改动了或者不想他人随意更改&#xff0c;我们可以如何保护PPT呢&#xff1f;下面小编就来分享两个常用的方法。 方法一&#xff1a;为PPT设置打开密码 为PPT设置打开密码是最直接有效…

活动预告|博睿数据将受邀出席GOPS全球运维大会上海站!

第二十四届 GOPS 全球运维大会暨研运数智化技术峰会上海站将于2024年10月18日-19日在上海中庚聚龙酒店召开。大会将为期2天&#xff0c;侧重大模型、DevOps、SRE、AIOps、BizDevOps、云原生及安全等热门技术领域。特设了如大模型 运维/研发测试、银行/证券数字化转型、平台工程…

九寨沟,智慧旅游新名片

九寨沟属于自然类景区&#xff0c;以优美的自然风光取胜&#xff0c;景区文化内涵相对缺失。智慧化和文旅融合是智慧文旅景区的两个必备条件&#xff0c;九寨沟在智慧文旅景区建设过程中&#xff0c;经历了两个阶段&#xff0c;先是从传统景区迈向智慧景区&#xff0c;然后是充…

设计模式:单例

一.什么是单例模式 单例模式是一种设计模式&#xff0c;指在整个程序生命周期中有且仅有一个实例的类。可以分为懒汉式以及饿汉式。 懒汉式&#xff1a;只有在类的实例被使用时才生成唯一实例。但是存在线程安全以及内存泄露的问题。可以节省系统资源。 饿汉式&#xff1a;程序…

10万+收藏!10万转发!AI绘画如何助力育儿赛道引爆短视频平台?

在自媒体领域&#xff0c;内容创作的竞争日益激烈&#xff0c;但育儿自媒体一直是一块热门且持久的“金矿”&#xff0c;吸引了无数创作者投身其中。然而&#xff0c;如何在这片红海中脱颖而出&#xff0c;成为了许多创作者面临的难题。而AI绘画的出现&#xff0c;无疑解决了创…

这种好看的航线图怎么绘制?超简单~~

今天这篇推文小编给大家介绍一个我一直想绘制的可视化作品-航线地图&#xff0c;网上有很多类似的教程&#xff0c;但在小编看来&#xff0c;都或多或少有些不完美&#xff0c;小编这次就对其进行完善和美化&#xff0c;主要内容如下&#xff1a; 航线地图所需数据处理 航线地…

Linux实践|设置静态 IP 地址

引言 如果您是 Linux 系统管理员&#xff0c;那么您将需要在系统上配置网络。与可以使用动态 IP 地址的台式机不同&#xff0c;在服务器基础设施上&#xff0c;您需要设置静态 IP 地址&#xff08;至少在大多数情况下&#xff09;。 本文[1]旨在向您展示如何在最常用的 Linux 发…

The 2024 ICPC Kunming Invitational Contest K. Permutation(交互 期望)

在知乎内查看 题目 思路来源 题解 首先特判n1的情况&#xff0c;其实也不用问 分治&#xff0c;假设当前解决到[l,r]&#xff0c;要递归的vector是x&#xff0c; 维护两个vector L、R&#xff0c;代表下一步要在[l,mid]和[mid1,r]分治的vector 每次将x random_shuffle后&a…

UE4 材质学习笔记01(什么是着色器/PBR基础)

1.什么是shader 着色器是控制屏幕上每个像素颜色的代码&#xff0c;这些代码通常在图形处理器上运行。 现如今游戏引擎使用先进的基于物理的渲染和照明。而且照明模型模型大多数是被锁定的。 因此我们创建着色器可以控制颜色&#xff0c;法线&#xff0c;粗糙度&#xff0c;…

C++竞赛初阶—— 石头剪子布

题目内容 石头剪子布&#xff0c;是一种猜拳游戏。起源于中国&#xff0c;然后传到日本、朝鲜等地&#xff0c;随着亚欧贸易的不断发展它传到了欧洲&#xff0c;到了近现代逐渐风靡世界。简单明了的规则&#xff0c;使得石头剪子布没有任何规则漏洞可钻&#xff0c;单次玩法比…

Qt实现Halcon窗口显示当前图片坐标

一、前言 Halcon加载图片的窗口&#xff0c;不仅能放大和缩小图片&#xff0c;还可以按住Ctrl键显示鼠标下的灰度值&#xff0c;这种方式很方便我们分析缺陷的灰度和对比度。 二、实现方式 ① 创建显示坐标和灰度的widget窗口 下图的是widget部件&#xff0c;使用了4个label控…

使用正则表达式删除文本的奇数行或者偶数行

用智谱清言和kimi搜出来的结果都没法在notepad生效&#xff0c;后面在overflow上找到的答案比较靠谱。 查找&#xff1a;^[^\n]*\n([^\n]*) 替换&#xff1a;\1 删除偶数行 查找&#xff1a;^([^\n]*)\n[^\n]* 替换&#xff1a;\1 代码解释 ^&#xff1a;这个符号代表字符…