ansible自动化运维(二)剧本、角色编写实战

news2025/1/17 5:55:46

😘作者简介:一名运维工作人员。
👊宣言:人生就是B(birth)和D(death)之间的C(choise),做好每一个选择。
🙏创作不易,动动小手给个点赞加关注吧,有什么意见评论区告诉我。

目录

一、剧本(playbook)

1、介绍

2、剧本组成

3、剧本编写规范

4、实战(编写搭建nginx的剧本)

1)本机安装nginx准备配置文件

2) 编写剧本

3)测试并执行剧本

测试剧本

 执行剧本

测试web2的nginx 

 5、使用剧本的变量(部署httpd)

1)本机安装httpd,准备配置文件

2)编写剧本

3)检测脚本

 4)执行剧本

5)使用web浏览器访问web1的9090端口 

 6、handlers

1)更改nginx的配置文件

2)编写剧本

 3)测试剧本

4)运行剧本

 5)使用web浏览器访问web2的8888端口

7、template 

1)准备模板

 2)修改nginx剧本

3)运行剧本并用查看web2的nginx的配置文件

8、tags模块

1)编写剧本(以创建目录为例)

2)运行剧本

3)查看web2主机的/test目录

 二、roles角色扮演

 1、介绍

2、实战(远程配置nginx)

1)目录结构

2)准备目录

3)准备file、template文件

4)编写任务

5)定义变量

6)定义handlers

7)编写剧本

8)测试并运行剧本

9)查看web2的配置文件,并用web浏览器访问web2的8090端口


一、剧本(playbook)

1、介绍

playbook是ansible用于配置,部署,和管理被控节点的剧本。通过playbook的详细描述,执行其中的tasks,可以让远端主机达到预期的状态。playbook是由一个或多个”play”组成的列表。 当对一台机器做环境初始化的时候往往需要不止做一件事情,这时使用playbook会更加适合。通过playbook你可以一次在多台机器执行多个指令。通过这种预先设计的配置保持了机器的配置统一,并很简单的执行日常任务。

ansible通过不同的模块实现相应的管理,管理的方式通过定义的清单文件(hosts)所管理的主机包括认证的方式连接的端口等。所有的功能都是通过调用不同的模块(modules)来完成不同的功能的。不管是执行单条命令还是play-book都是基于清单文件。

playbook格式:playbook由YMAL语言编写。YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写。

2、剧本组成

剧本的角色(play), 定义的是主机信息
剧本的任务(task), 定义的是具体任务
playbook组成部分:
1) 一个playbook有多个play组成
2) 一个play可以包含多个task任务
3) 简单理解为使用多个模块功能完成一件事

task:

        Variables:变量

        Templates:模板

        Handlers:触发器,当 changed 状态条件满足时,(notify)触发执行的操作。

3、剧本编写规范

编写规范遵循yaml语法规范

缩进规范 两个空格表示一个缩进 不平级标题之间一定要开头相隔两个空格

注意: 缩进只能以空格表示 tab会报错。

字典规范 冒号后面必须要有空格

注意: 冒号结尾时不需要有空格 注释信息中冒号也不需要。

列表规范: 横线后面要有一个空格

4、实战(编写搭建nginx的剧本)

1)本机安装nginx准备配置文件

#安装nginx这里我之前安装好的
[root@localhost ~]# yum install  -y nginx
上次元数据过期检查:0:40:12 前,执行于 2023年07月26日 星期三 08时23分53秒。
软件包 nginx-1:1.22.1-2.el9.x86_64 已安装。
依赖关系解决。
无需任何处理。
完毕!
#创建一个存放nginx配置文件的目录,用作copy到远程服务器使用
[root@localhost ~]# mkdir /nginx
[root@localhost ~]# cp /etc/nginx/nginx.conf /nginx/
#更改nginx的默认端口,用作检测推送
[root@localhost ~]# sed -i '/listen/s/80/8090/g' /nginx/nginx.conf

2) 编写剧本

[root@localhost ~]# vim nginx.yml
[root@localhost ~]# cat nginx.yml 
- hosts: nginx
  tasks:
    - name: install nginx
      yum: name=nginx state=present
    - name: copy nginx conf
      copy: src=/nginx/nginx.conf dest=/etc/nginx/nginx.conf
    - name: start service
      service: name=nginx state=started enabled=yes

剧本解释:

- hosts:指定需要执行剧本的主机

tasks:任务列表

- name:类似于注释

   ansible模块相关命令

3)测试并执行剧本

ansible-playbook nginx.yml  --syntax-check        检验语法
ansible-playbook nginx.yml --list-tasks        列出任务
ansible-playbook nginx.yml --list-hosts        列出主机
ansible-playbook nginx.yml        执行

测试剧本

#测试剧本语法,无报错即可,报错根据报错提示去修改剧本
[root@localhost ~]# ansible-playbook  nginx.yml --syntax-check

playbook: nginx.yml
#列出任务列表,展示有哪些任务需要执行
[root@localhost ~]# ansible-playbook nginx.yml  --list-tasks

playbook: nginx.yml

  play #1 (nginx): nginx	TAGS: []
    tasks:
      install nginx	TAGS: []
      copy nginx conf	TAGS: []
      start service	TAGS: []
#列出需要执行剧本的主机
[root@localhost ~]# ansible-playbook nginx.yml --list-hosts

playbook: nginx.yml

  play #1 (nginx): nginx	TAGS: []
    pattern: ['nginx']
    hosts (1):
      web2

 执行剧本

[root@localhost ~]# ansible-playbook nginx.yml 

PLAY [nginx] ************************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************************
ok: [web2]        #web2可以执行

TASK [install nginx] ****************************************************************************************************************************************************
changed: [web2]    #web2安装了nginx

TASK [copy nginx conf] **************************************************************************************************************************************************
changed: [web2]    #拷贝配置文件到web2成功

TASK [start service] ****************************************************************************************************************************************************
changed: [web2]    #启动nginx成功

PLAY RECAP **************************************************************************************************************************************************************
web2                       : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

测试web2的nginx 

用浏览器分别访问web2的80端口和8090端口。

 80端口访问失败。

 8090端口访问成功,说明剧本执行成功,web2的nginx配置文件是刚刚在ansible主机修改的配置文件。

 5、使用剧本的变量(部署httpd)

在剧本中定义变量并使用变量,比如部署软件的时候,将软件的名字和配置文件的路径设置为变量,这样一个剧本只需要更改变量即可完成剧本的复用。

下面在web1使用剧本部署httpd,并且使用变量来测试。

1)本机安装httpd,准备配置文件

思路:准备一个httpd文件夹,将httpd配置文件拷贝到httpd文件夹备用,并且更改配置文件的端口为9090,以便检测远程主机的配置文件是否是推送过去的。

[root@localhost ~]# mkdir /httpd
[root@localhost ~]# cp /etc/httpd/conf/httpd.conf  /httpd/
[root@localhost ~]# sed -i '/^Listen/s/80/9090/g' /httpd/httpd.conf

2)编写剧本

定义变量:

 vars:

      - key:values

引用变量{{key}}

[root@localhost ~]# vim http.yml
[root@localhost ~]# cat http.yml 
- hosts: http
  vars:            #定义变量
    - pkg: httpd    #包名
    - svc: httpd    #服务名
  tasks:
    - name: install httpd
      yum: name={{pkg}} state=present    #引用包名变量
    - name: cpoy http conf
      copy: src=/httpd/httpd.conf dest=/etc/httpd/conf/httpd.conf
    - name: start httpd service
      service: name={{svc}} state=started enabled=yes    #引用服务名变量

3)检测脚本

[root@localhost ~]# ansible-playbook http.yml  --syntax-check
[DEPRECATION WARNING]: Specifying a list of dictionaries for vars is deprecated in favor of specifying a dictionary. This feature will be removed in version 2.18. 
Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.

playbook: http.yml

 4)执行剧本

[root@localhost ~]# ansible-playbook http.yml 
[DEPRECATION WARNING]: Specifying a list of dictionaries for vars is deprecated in favor of specifying a dictionary. This feature will be removed in version 2.18. 
Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.

PLAY [http] *************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************
ok: [web1]

TASK [install httpd] ****************************************************************************************************************************************************
changed: [web1]

TASK [copy http conf] ***************************************************************************************************************************************************
changed: [web1]

TASK [start httpd service] **********************************************************************************************************************************************
changed: [web1]

PLAY RECAP **************************************************************************************************************************************************************
web1                       : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

5)使用web浏览器访问web1的9090端口 

 6、handlers

触发器,当 changed 状态条件满足时,(notify)触发执行的操作。

在需要执行触发器的位置设置

notify:标记

然后在定义触发器

handlers:

 - name:标记

   触发执行命令

注意:notify的标记要和handlers的标记要一致,这里是一一对应的。

在配置文件发生改变的时候,需要重启服务才能生效,所以一般在拷贝配置文件任务那里添加一个notify,在触发器位置执行重启服务器。

这里使用刚刚nginx的剧本来进行测试。

1)更改nginx的配置文件

[root@localhost ~]# sed -i '/listen/s/8090/8888/g' /nginx/nginx.conf

将默认端口改为8888 

2)编写剧本

[root@localhost ~]# vim nginx.yml 
[root@localhost ~]# cat nginx.yml 
- hosts: nginx
  tasks:
    - name: install nginx
      yum: name=nginx state=present
    - name: copy nginx conf
      copy: src=/nginx/nginx.conf dest=/etc/nginx/nginx.conf
      notify: restart nginx service
    - name: update index.html
      shell: echo 'i am sure' > /usr/share/nginx/html/index.html
    - name: start service
      service: name=nginx state=started enabled=yes
  handlers:
    - name: restart nginx service
      service: name=nginx state=restarted

 3)测试剧本

[root@localhost ~]# ansible-playbook nginx.yml --syntax-check

playbook: nginx.yml

4)运行剧本

 5)使用web浏览器访问web2的8888端口

 成功!!!

7、template 

可以看作是一个编译过的模板文件,用来产生目标文本,传递Python的变量给模板去替换模板中的标记。

1)准备模板

将原本的配置文件重命名改成.j2文件作为配置文件模板。

然后更改模板内容。

在主机清单定义一个变量

[root@localhost ~]# mv /nginx/nginx.conf  /nginx/nginx.conf.j2

 这里将模板文件的listen处改为使用变量ansible_http_port。

 2)修改nginx剧本

- hosts: nginx
  tasks:
    - name: install nginx
      yum: name=nginx state=present
    - name: nginx conf
      template: src=/nginx/nginx.conf.j2 dest=/etc/nginx/nginx.conf
      notify: restart nginx service
    - name: update index.html
      shell: echo 'i  am sure' > /usr/share/nginx/html/index.html
    - name: start service
      service: name=nginx state=started enabled=yes
  handlers:
    - name: restart nginx service
      service: name=nginx state=restarted

将原来的copy改为使用模板来推送配置文件

3)运行剧本并用查看web2的nginx的配置文件

8、tags模块

可以在一个playbook中为某个或某些任务定义“标签”,在执行此playbook时通过ansible-playbook命令使用–tags选项能实现仅运行指定的tasks。
playbook还提供了一个特殊的tags为always。作用就是当使用always当tags的task时,无论执行哪一个tags时,定义有always的tags都会执行。

1)编写剧本(以创建目录为例)

[root@localhost ~]# cat tags.yml 
- hosts: nginx
  tasks:
    - name: mkdir dir1
      file: name=/test/dir1 state=directory
      tags:
        - first
    - name: mkdir dir2
      file: name=/test/dir2 state=directory
    - name: nkdir dir3
      file: name=/test/dir3 state=directory
      tags:
        - always

这里给dir1任务打了first的标签 ,给dir2任务没有打标签,给dir3打了always的标签

2)运行剧本

看到运行提示,只有dir1和dir3被创建。

3)查看web2主机的/test目录

[root@localhost ~]# ansible nginx -m shell -a 'ls /test'
web2 | CHANGED | rc=0 >>
dir1
dir3

发现只有dir1和dir3,因为在运行剧本的时候加了tags=“first”所以剧本中只有打first标签的任务和打always的任务被执行,其余任务不会被执行。


 二、roles角色扮演

 1、介绍

roles则是在ansible中,playbooks的目录组织结构。
将代码或文件进行模块化,成为roles的文件目录组织结构,
易读,代码可重用,层次清晰。

2、实战(远程配置nginx)

1)目录结构

结构介绍:

  • nginx 角色名
  • files  普通文件,用来存放由 copy 模块或 script 模块调用的文件。
  • handlers  触发器程序,此目录应当包含一个 main.yml 文件,用于定义此角色中触发条件时执行的动作。
  • tasks  主任务,此目录应当包含一个 main.yml 文件,用于定义此角色的任务列表,此文件可以使用 include 包含其它的位于此目录的 task 文件。
  • templates 金甲模板(有变量的文件),用来存放 j2 模板,template 模块会自动在此目录中寻找 j2 模板文件。
  • vars 自定义变量,此目录应当包含一个 main.yml 文件,用于定义此角色用到的变量。
  • f除开files目录和templates目录不需要创建main.yml文件,其余都要各个目录下都要创建

2)准备目录

mkdir roles/nginx/{files,handlers,tasks,templates,vars} -p
touch roles/site.yaml roles/nginx/{handlers,tasks,vars}/main.yaml
[root@localhost ~]# tree roles/
roles/
├── nginx
│   ├── files
│   ├── handlers
│   │   └── main.yaml
│   ├── tasks
│   │   └── main.yaml
│   ├── templates
│   └── vars
│       └── main.yaml
└── site.yaml

6 directories, 4 files

3)准备file、template文件

制作nginx主页,以及金甲模板,并修改模板。

[root@localhost ~]# cp /nginx/nginx.conf.j2  roles/nginx/templates/
[root@localhost ~]# echo "<h1>I am Sure Nginx<h1/>" > roles/nginx/files/index.html
[root@localhost ~]# tree roles/
roles/
├── nginx
│   ├── files
│   │   └── index.html
│   ├── handlers
│   │   └── main.yaml
│   ├── tasks
│   │   └── main.yaml
│   ├── templates
│   │   └── nginx.conf.j2
│   └── vars
│       └── main.yaml
└── site.yaml

4)编写任务

在tasks目录下的main.yaml写

[root@localhost ~]# cat roles/nginx/tasks/main.yaml 
  tasks:
    - name: install nginx
      yum: name={{pkg}} state=present
    - name: set nginx conf
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      notify: restart nginx service
    - name: copy nginx index
      copy: src=index.html dest=/usr/share/nginx/html/index.html
    - name: start nginx service
      service: name={{svc}} state=started enabled=yes

5)定义变量

在vars目录下的main.yaml编写。

[root@localhost ~]# cat roles/nginx/vars/main.yaml 
port: 8090
work_connection: 1024
pkg: nginx
svc: nginx

6)定义handlers

在handlers目录下的main.yaml编写。

[root@localhost ~]# cat roles/nginx/handlers/main.yaml 
- name: restart nginx service
  service: name={{svc}} state=restarted

7)编写剧本

在site.yaml编写

剧本中的角色可以是多个,这里是以一个nginx为例。

[root@localhost ~]# cat roles/site.yaml 
- hosts: nginx
  roles:
    - nginx

8)测试并运行剧本

[root@localhost ~]# ansible-playbook roles/site.yaml --syntax-check

playbook: roles/site.yaml

[root@localhost ~]# ansible-playbook roles/site.yaml 
[WARNING]: Found variable using reserved name: port

PLAY [nginx] ************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************
ok: [web2]

TASK [nginx : install nginx] ********************************************************************************************************************************************
ok: [web2]

TASK [nginx : set nginx conf] *******************************************************************************************************************************************
changed: [web2]

TASK [nginx : copy nginx index] *****************************************************************************************************************************************
changed: [web2]

TASK [nginx : start nginx service] **************************************************************************************************************************************
ok: [web2]

RUNNING HANDLER [nginx : restart nginx service] *************************************************************************************************************************
changed: [web2]

PLAY RECAP **************************************************************************************************************************************************************
web2                       : ok=6    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

9)查看web2的配置文件,并用web浏览器访问web2的8090端口

[root@localhost ~]# ansible nginx -m shell -a 'cat /etc/nginx/nginx.conf | grep listen'
web2 | CHANGED | rc=0 >>
        listen       8090;
        listen       [::]:8090;
#        listen       443 ssl http2;
#        listen       [::]:443 ssl http2;
[root@localhost ~]# ansible nginx -m shell -a 'cat /etc/nginx/nginx.conf | grep worker_connection'
web2 | CHANGED | rc=0 >>
    worker_connections 1024;

web2的nginx的配置文件中发现端口为8090,worker_connections是1024,和刚刚设置的变量一致。 

 访问web2的8090端口展示的页面正是刚刚自己自定义的网络首页。

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

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

相关文章

在C语言中,变量主要的作用是什么?

常量记忆数据只能存储一个固定的数据&#xff0c;永远不变&#xff0c;所以这当然不能算得上是记忆数据 变量存储的数据可以改变&#xff0c;你可以让它记忆5&#xff0c;下一步它可以变为10 如果你还无法理解 那么请不用尝试变量编程实现以下&#xff1a; 输入一个100之内…

Cesium态势标绘专题-简单箭头(标绘+编辑)

标绘专题介绍:态势标绘专题介绍_总要学点什么的博客-CSDN博客 入口文件:Cesium态势标绘专题-入口_总要学点什么的博客-CSDN博客 辅助文件:Cesium态势标绘专题-辅助文件_总要学点什么的博客-CSDN博客 本专题没有废话,只有代码,代码中涉及到的引入文件方法,从上面三个链…

NoSQL-Redis持久化

NoSQL-Redis持久化 一、Redis 高可用&#xff1a;1.概述&#xff1a; 二、Redis持久化&#xff1a;1.持久化的功能&#xff1a;2.Redis 提供两种方式进行持久化&#xff1a; 三、RDB 持久化&#xff1a;1.定义&#xff1a;2.触发条件&#xff1a;3.执行流程&#xff1a;4.启动时…

地下水除砷工艺盘点:生物法、混凝法、沉淀法、吸附法和离子交换法

砷(As)为非人体必需元素&#xff0c;既不溶解于水又不溶解于酸&#xff0c;在自然界有三价无机态 As(III)、五价无机态 As(V)以及有机砷MMA(甲基胂酸)、DMA(二甲基胂酸)、TMA(三甲基胂酸)等。 砷在水体中主要以三价和五价的无机酸形式存在&#xff0c;三价砷的毒性更强&#xf…

作为一名测试工程师,你知道“微信红包”怎么测试吗?

测试思维 测试任何事物的测试思路可以总结如下&#xff1a; 第一步&#xff1a;梳理产品的核心业务流程&#xff1a;明白这是个什么项目&#xff0c;实现了什么业务&#xff0c;以及是怎么实现的&#xff1f; 这个步骤一般是参考公司的需求文档来的&#xff0c;如果产品提供…

Mr. Cappuccino的第52杯咖啡——Mybatis环境搭建与使用

Mybatis环境搭建与使用 Mybatis介绍Mybatis环境搭建与使用基于XML方式-原生方式开发创建数据库表项目准备项目结构项目代码实体类中添加有参构造方法产生的问题 基于XML方式-mapper代理开发项目准备项目结构项目代码SQL映射文件中namespace未设置为接口全限定名产生的问题 基于…

ESP32 LVGL:使用menuconfig配置LVGL会导致全部文件重新编译问题解决

问题描述 在使用ESP32 IDF LVGL时&#xff0c;我们可以通过idf.py menuconfig来对LVGL进行配置&#xff0c;但是每次使用idf.py menuconfig配置完LVGL后&#xff0c;由于修改了工程的sdkconfig文件&#xff0c;因此所有的文件都需要重新编译。如下图&#xff1a; 需要编译几千…

Mkdocs中利用Js实现大小圈鼠标拖动样式

在docs/javascripts/extra.js下复制粘贴&#xff1a; var CURSOR;Math.lerp (a, b, n) > (1 - n) * a n * b;const getStyle (el, attr) > {try {return window.getComputedStyle? window.getComputedStyle(el)[attr]: el.currentStyle[attr];} catch (e) {}return …

Java并发(十三)----共享存在的问题

1、小故事 老王&#xff08;操作系统&#xff09;有一个功能强大的算盘&#xff08;CPU&#xff09;&#xff0c;现在想把它租出去&#xff0c;赚一点外快 小南、小女&#xff08;不同的线程&#xff09;来使用这个算盘来进行一些计算&#xff0c;并按照时间给老王支付费用…

多元函数习题

目录 例题1&#xff1a; 例题2&#xff1a; 例题3&#xff1a; 证明题 例1&#xff1a; 例题2 ​编辑 例题3&#xff1a; 例题4&#xff1a; 例题1&#xff1a; 第二问的解法2&#xff1a; 例题2&#xff1a; 选择D&#xff0c;偏导数存在与函数连续并没有关系。 例题3&…

Git竞合处理

Gitee新建一个代码仓库&#xff0c;clone到本地&#xff0c;模拟竞合的情况出现 这里仓库已经配好了ssh&#xff0c;所以没有添加账户绑定的步骤 clone到本地 模拟A同学Clone代码 git clone 项目地址新建一个文件&#xff0c;上传到仓库 push到仓库 代码仓库已经可以看到了…

mysql-速成补充

目录 1.演示事务 ​编辑 1.1 read-uncommitted 1.2 read-committed 1.3 repeatable read 1.4 幻读 1.5 serializable 1.6 savepoint 2 变量 2.1 语法 2.2 举例 3 存储过程和函数 3.1 特点和语法 3.2 举例 4.函数 4.1 语法 4.2 举例 5 流程控制 5.1 分…

window.location.protocol使用实战图片不同浏览器显示问题解决方案

图片在不同浏览器可能会显示不出来个别原因分析&#xff0c; 如火狐浏览器协议类型会有问题 但是谷歌可以 解决方案&#xff1a;将写死的协议 如http换成window.location.protocol就可以了 前景&#xff1a;前台项目和后台项目有时返回的并不是图片全路径 &#xff0c;有时候…

接口测试进阶之数据模板

大家好久不见了。今天的文章将介绍jinja2模板在接口测试数据上的应用。 这几个月我在想&#xff0c;进阶系列要怎么写。 毕竟很多情况下&#xff0c;我觉得写技术文章和做培训一样&#xff0c;都会有两个结果&#xff1a; 1.是需要这些知识的人看不懂。 2.是看得懂的人不需要…

数值线性代数: 共轭梯度法

本文记录共轭梯度噶求解线性方程组的原理及流程。 零、预修 0.1 LU分解 设&#xff0c;若对于&#xff0c;均有&#xff0c;则存在下三角矩阵和上三角矩阵&#xff0c;使得。 设&#xff0c;若对于&#xff0c;均有&#xff0c;则存在唯一的下三角矩阵和上三角矩阵&#xff…

【云原生】Docker私有仓库registry

目录 1&#xff09;用docker容器运行registry私有仓库服务。 2&#xff09;运行私有仓库服务 3&#xff09;镜像重命名(要上传的镜像名需要注明私仓的ip) 4&#xff09;编辑docker配置文件(因为默认是拉取docker官方的镜像&#xff0c;需要重新指定) 5&#xff09;其他dock…

walkRE裁剪面域内部--制作面洞

1、打开WalkRE软件&#xff0c;根据模板新建工程&#xff0c;如下&#xff1a; 2、绘制待裁剪区域和裁剪区域。如下&#xff1a; 将中间的矩形转换成面状的&#xff0c;如下&#xff1a; 3、裁剪掉中间内部的矩形&#xff0c;保留中间面状矩形的外部&#xff0c;如下&#xff1…

【算法提高:动态规划】1.2 最长上升子序列模型(TODO:最长公共上升子序列)

文章目录 题目列表1017. 怪盗基德的滑翔翼1014. 登山482. 合唱队形1012. 友好城市&#xff08;⭐排序后 最长上升子序列模型&#xff09;1016. 最大上升子序列和1010. 拦截导弹解法1——最长递减子序列 贪心解法2——最长递减子序列 最长递增子序列&#xff08;⭐贪心结论&am…

2023年你不容错过的软件测试项目实战(APP项目实战)免费版

前言 最近很多的人都在问我有没有什么项目可以用来练手&#xff0c;正好我这里有一个比较适合练手的项目&#xff0c;那就给大家安利一下吧&#xff0c;废话就不多说了。 项目名称&#xff1a; APP项目实战 项目说明&#xff1a; 本项目里面包括了功能测试、性能测试、安全…

MATLAB与ROS联合仿真——实例程序搭建思路

一、基础运动控制实例程序搭建思路 1、需要完成的任务&#xff1a; &#xff08;1&#xff09;通过设定小车运动的速度及转角来控制ROS中小车运动。 &#xff08;2&#xff09;通过键盘输入指令控制ROS中小车运动&#xff0c;键盘输入w小车前行&#xff0c;s小车后退&#x…