Playbook的用法
目录
Playbook
Playbook 与 Ad-Hoc 对比
YAML 语言特性
YAML语法简介
支持的数据类型
写法格式
1 scalar 标量 建议缩进两个空格,可多
2 Dictionary 字典
3 List 列表
三种常见的数据格式
Playbook 核心组件 不要用 tab 可以#注释
hosts
remote_user 组件 指定账户默认root
nginx安装 #默认会去files文件里找 把文件放里面不用加前面的
性能优化
方法1
方法2
register 注册变量
在主机清单中定义主机和主机组的变量
变量的优先级从高到低如下
Template 模板
jinja2语言
template 专门存放模板文件
template中使用流程控制 for 和 if
for 循环
if 条件判断
使用循环迭代
迭代 loop (with_items)
until 循环
with_lines 逐行处理
条件判断 when
分组 block
关闭 changed 状态
利用 changed_when 检查task返回结果
滚动执行
委派至其它主机执行
只执行一次
环境变量
Yaml 文件的相互调用
import_playbook 由一个yml统一调用
Roles 角色
roles目录结构:
Roles各目录作用
Playbook

- 一个 playbook(剧本)文件是一个YAML语言编写的文本文件
- 通常一个playbook只包括一个play ,但可以包括多个Play
- 一个 play的主要包括两部分: 主机和tasks. 即实现在指定一组主机上执行一个tasks定义好的任务列 表。
- 一个tasks中可以有一个或多个task任务 每一个Task本质上就是调用ansible的一个module
- 在复杂场景中,一个playbook中也可以包括多个play,实现对多组不同的主机执行不同的任务
Playbook 与 Ad-Hoc 对比
- Playbook是对多个 AD-Hoc 的一种编排组合的实现方式
- Playbook能控制任务执行的先后顺序
- Playbook可以持久保存到文件中从而方便多次调用运行,而Ad-Hoc只能临时运行。
- Playbook适合复杂的重复性的任务,而Ad-Hoc适合做快速简单的一次性任务
YAML 语言特性
- YAML的可读性好
- YAML和脚本语言的交互性好
- YAML使用实现语言的数据类型
- YAML有一个一致的信息模型
- YAML易于实现
- YAML可以基于流来处理
- YAML表达能力强,扩展性好
YAML语法简介
- 在单一文件第一行,用连续三个连字号"-" 开始,还有选择性的连续三个点号( ... )用来表示文件的结 尾
- 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
- 使用#号注释代码
- 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换 行来实现的
- 缩进不支持tab,必须使用空格进行缩进
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- YAML文件内容是区别大小写的,key/value的值均需大小写敏感
- 多个key/value可同行写也可换行写,同行使用,分隔
- key后面冒号要加一个空格 比如: key: value value可是个字符串,也可是另一个列表
- YAML文件扩展名通常为yml或yaml
支持的数据类型
YAML 支持以下常用几种数据类型:
- 标量:单个的、不可再分的值
- 对象:键值对的集合,又称为: 字典(dictionary)/ 哈希(hashes) / 映射(mapping)
- 数组:一组按次序排列的值,又称为: 列表(list)/ 序列(sequence)
写法格式
1 scalar 标量 建议缩进两个空格,可多
key对应value
name: wang
age: 18
使用缩进的方式
name:
wang
age:
18
2 Dictionary 字典
格式
格式
使用缩进方式
account:
name: wang
age: 18
gender: male
范例:
#不同行
# An employee record
name: Example Developer
job: Developer
skill: Elite(社会精英)
#同一行,也可以将key:value放置于{}中进行表示,用,分隔多个key:value
# An employee record
{name: "Example Developer", job: "Developer", skill: "Elite"}
3 List 列表
列表由多个元素组成, 本质就是数组
每个元素放在不同行,每个元素一行,且元素前均使用中横线 - 开头,并且中横线 - 和元素之间有一个空
格
也可以将所有元素用 [ ] 括起来放在同一行,每个元素之间用逗号分隔
格式
course: [ linux , golang , python ]
也可以写成以 - 开头的多行
course:
- linux
- golang
- python
元素里也可以包含字典
course:
- linux: manjaro
price: 10000
- golang: gin
class: 49
- python: django
范例:
#不同行,行以-开头,后面有一个空格
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
#同一行
[Apple,Orange,Strawberry,Mango]
范例:YAML 表示一个家庭
name: John Smith
age: 41
gender: Male
spouse: { name: Jane Smith, age: 37, gender: Female } # 写在一行里
name: Jane Smith #也可以写成多行
age: 37
gender: Femalechildren: [ {name: Jimmy Smith,age: 17, gender: Male}, {name: Jenny Smith, age:
13, gender: Female}, {name: hao Smith, age: 20, gender: Male } ] #写在一行
- name: Jimmy Smith #写在多行,更为推荐的写法
age: 17
gender: Male
- {name: Jenny Smith, age: 13, gender: Female}
- {name: hao Smith, age: 20, gender: Male }
三种常见的数据格式
- XML:Extensible Markup Language,可扩展标记语言,可用于数据交换和配置
- JSON:JavaScript Object Notation, JavaScript 对象表记法,主要用来数据交换或配置,不支持注 释
- YAML:YAML Ain't Markup Language YAML 不是一种标记语言, 主要用来配置,大小写敏感, 不支持tab
可以用工具互相转换,参考网站: JSON在线解析及格式化验证 - JSON.cn
Playbook 核心组件 不要用 tab 可以#注释
一个playbook 中由多个组件组成,其中所用到的常见组件类型如下:
- Hosts 执行的远程主机列表
- Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需最 少元素需包括 name 和 task,一个name只能包括一个task
- Variables 内置变量或自定义变量在playbook中调用
- Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
- tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此 会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地 长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
vim hello.yaml
--- 不强制写
# 第一个Playbook 文件- hosts: webservers #针对的主机 可多个tasks: #针对的任务- name: test ping #这个任务做什么的 可汉字ping: #有参数可以写 没有就这样- name: shell pwd #做什么shell: 'hostname -I' #命令及参数
ansible-playbook -C hello.yaml #模拟执行检查
ansible-playbook --syntax-check hello.yaml #语法检查
[root@ubuntu2004 ~]#ansible-playbook -vv hello.yaml #-v查看信息 最多4个 可以不加

hosts
组件 Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用 于指定要执行指定任务的主机,须事先定义在主机清单中
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
webservers:dbservers #或者,两个组的并集
webservers:&dbservers #与,两个组的交集
webservers:!dbservers #在webservers组,但不在dbservers组
案例
- hosts: webservers:appservers
remote_user 组件 指定账户默认root
remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可 用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: webserversremote_user: roottasks:- name: test connectionping:remote_user: wangesudo: yes #默认sudo为rootsudo_user:wang #将wange用户sudo为wang
nginx安装 #默认会去files文件里找 把文件放里面不用加前面的
---
# nginx
- hosts: 10.0.0.8remote_user: roottasks:- name: 安装yum:name: nginxstate: present- name: 复制copy:src: /data/nginx.conf #默认会去files文件里找 把文件放里面不用加前面的 dest: /etc/nginx/nginx.conf 也是- name: 页面copy:src: /data/index.htmldest: /usr/share/nginx/html/index.html- name: 启动service:name: nginxstate:startedenabled: yes
性能优化
每次执行playbook,默认会收集每个主机的所有facts变量,将会导致速度很慢,可以采用下面方法加速
方法1
关闭facts采集加速执行,此方法将导致无法使用facts变量
- hosts: all
gather_facts: no
方法2
当使用 gather_facts: no 关闭 facts,确实能加速 Ansible 执行,但是有时候又需要使用 facts 中的内容,还希望执行的速度快,这时候可以设置facts 的缓存,将facts变量信息存在redis服务器中
[root@ansible ~]# cat /etc/ansible/ansible.cfg
[defaults]
# smart 表示默认收集 facts,但 facts 已有的情况下不会收集,即使用缓存 facts
# implicit 表示默认收集 facts,要禁止收集,必须使用 gather_facts: False
# explicit 则表示默认不收集,要显式收集,必须使用gather_facts: Truegathering = smart #在使用 facts 缓存时设置为smart
fact_caching_timeout = 86400 #缓存时长
fact_caching = redis #缓存存在redis中
fact_caching_connection = 10.0.0.100:6379:0 #0表示redis的0号数据库
#若redis设置了密码
fact_caching_connection = 10.0.0.100:6379:0:password
register 注册变量
在playbook中可以使用register将捕获命令的输出保存在临时变量中,方便后续调用此变量,比如可以使用debug模块进行显示输出
[root@centos8 ~]#cat register1.yml
- hosts: dbservers
tasks:
- name: get variable
shell: hostname
register: name
- name: "print variable"
debug:
msg: "{{ name }}" #输出register注册的name变量的全部信息,注意变量要加" "引起来
#msg: "{{ name.cmd }}" #显示命令
#msg: "{{ name.rc }}" #显示命令成功与否
#msg: "{{ name.stdout }}" #显示命令的输出结果为字符串形式,所有结果都放
在一行里显示,适合于结果是单行输出
#msg: "{{ name.stdout_lines }}" #显示命令的输出结果为列表形式,逐行标准输出,适
用于多行显示
#msg: "{{ name['stdout_lines'] }}" #显示命令的执行结果为列表形式,和效果上面相同
#msg: "{{ name.stdout_lines[0] }}" #显示命令的输出结果的列表中的第一个元素
#说明
第一个 task 中,使用了 register 注册变量名为 name ;当 shell 模块执行完毕后,会将数据放到该
变量中。
第二给 task 中,使用了 debug 模块,并从变量name中获取数据
- hosts: webserverstasks:- name: get variableshell: hostnameregister: name- name: "print variable"debug:#msg: "{{ name }}"msg: "{{ name.stdout_lines }}"

在主机清单中定义主机和主机组的变量
[webservers]
10.0.0.101 host=web01
10.0.0.102 host=web02
[webservers:vars]
domain=wang
[appservers]
10.0.0.[7:8]
10.0.0.101
[all:vars]
suffix=edu
[root@ubuntu2004 ansible]#vim yum5.yaml- hosts: webserverstasks:- name: set hostnamehostname:name: "{{ host }}.{{ domain }}.{{ suffix }}"


2

将变量放在文件里,不放在变量也行
变量的优先级从高到低如下
-e 选项定义变量 -->playbook中vars_files --> playbook中vars变量定义 -->host_vars/主机名
文件 -->主机清单中主机变量--> group_vars/主机组名文件-->group_vars/all文件--> 主机清单组变量
Template 模板
模板是一个文本文件,可以用于根据每个主机的不同环境而为生成不同的文件
模板文件中支持嵌套jinja2语言的指令,来实现变量,条件判断,循环等功能
需要使用template模块实现文件的复制到远程主机,但和copy模块不同,复制过去的文件每个主机可以会有所不同
jinja2语言
Jinja2 是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。 它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全:
特性:
- 沙箱中执行
- 强大的 HTML 自动转义系统保护系统免受 XSS
- 模板继承
- 及时编译最优的 python 代码
- 可选提前编译模板的时间
- 易于调试。异常的行数直接指向模板中的对应行。
- 可配置的语法
template 专门存放模板文件
template功能:可以根据和参考模块文件,动态生成相类似的配置文件
template文件存建议放于templates目录下,且命名为 .j2 结尾
yaml/yml 文件和templates目录平级,此时playbook中指定模板文件时可不用指定路径, 目录结构如下
./
├── temnginx.yml
└── templates
└── nginx.conf.j2
template变更替换
#修改文件nginx.conf.j2
[root@ansible ~]#mkdir templates
[root@ansible ~]#vim templates/nginx.conf.j2
......
worker_processes {{ ansible_processor_vcpus }}; 本机的cpu个数,可以+*等
......
安装nginx指定内核
template中使用流程控制 for 和 if
template中也可以使用流程控制 for 循环和 if 条件判断,实现动态生成文件功能
for 循环
格式
{% for i in EXPR %}
...
{% endfor %}#示例:
{% for i in range(1,10) %}
server_name web{{i}};
{% endfor %}
for.yam #引用下面

test.conf.j2


#temlnginx2.yml
---
- hosts: webservers
remote_user: root
vars:
nginx_vhosts:
- 81
- 82
- 83
tasks:
- name: template config
template: src=nginx.conf2.j2 dest=/data/nginx.conf#templates/nginx.conf2.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost }}
}
{% endfor %}
ansible-playbook -C templnginx2.yml --limit 10.0.0.8#生成的结果:
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
循环,提取建网站


结果

if 条件判断
有的有server_name有的没有if判断



使用循环迭代
迭代:当有需要重复性执行的任务时,可以使用迭代机制
迭代 loop (with_items)
- 对迭代项的引用,固定内置变量名为"item"
- 要在task中使用with_items给定要迭代的元素列表
- 注意: ansible2.5版本后,可以用loop代替with_items
列表元素格式:
字符串
- 字典 key: value
类似if循环
---
- hosts: webservers
remote_user: root
tasks:
- name: add several users
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
- testuser3#上面语句的功能等同于下面的语句
- name: add several users
user: name=testuser1 state=present groups=wheel
- name: add several users
user: name=testuser2 state=present groups=wheel
- name: add several users
user: name=testuser3 state=present groups=wheel
范例: 安装多个软件包
#方法1
# cat install_packages.yml
- hosts: webserverstasks:- name: Installed Httpd Php-fpm Packageyum: name={{ pack }} state=latestvars:pack:- httpd- php-fpm
#方法2
# cat install_packages2.yml
- hosts: webserverstasks:- name: Installed Httpd Php-fpm Packageyum:name: {{ item }}state: latestloop:- httpd- php-fpm
# cat install_packages3.yml
---
- hosts:webserversremote_user: roottasks- name: install some packagesyum: name={{ item }} state=presentwith_items:- nginx- memcached- php-fpm
until 循环
#until为false时才会执行循环,为true则退出循环
[root@ansible ansible]#cat until.yml
- hosts: localhost
gather_facts: false
tasks:
- debug: msg="until"
until: false
retries: 3 #默认值即为3次
delay: 1
范例: 以轮询的方式等待服务同步完成
- name: 以轮询的方式等待服务同步完成
shell: "systemctl is-active mysqld.service" #执行命令
register: mysqld_status #结果保存在在里面
until: '"active" in mysqld_status.stdout' #检查这里里面是否有,有退出
retries: 8 #试几次
delay: 8 #停顿几秒
with_lines 逐行处理
逐行处理,一行打印一次
[root@ansible ansible]#cat with_lines.yml
- hosts: localhost
tasks:
- debug: msg={{ item }}
with_lines: ps aux
条件判断 when
when语句可以实现条件测试。如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过在task后添加when子句即可使用jinja2的语法格式条件测试
范例: 判断OS版本
[root@ansible ansible]#cat when.yml
- hosts: alltasks:- name: install httpdyum:name: "httpd"when:- ansible_distribution_file_variety == "RedHat"- name: install packageapt:name: "apache2"when:- ansible_distribution_file_variety == "Debian"

范例: 数据类型转换
- hosts: appserverstasks:- shell: echo "only on Red Hat 6, derivatives, and liter"when: ansible_distribution_file_variety == "RedHat" and ansible_facts['lsb']['major_release'] | int > 7
分组 block
当想在满足同样条件下,执行多个任务时,就需要分组。而不再针对每个任务都是用
- hosts: appserverstasks:- block:- shell: echo "task1"- shell: echo "task2"when:- ansible_distribution_file_variety == "RedHat"- ansible_facts['lsb']['major_release'] | int > 7
关闭 changed 状态
当确定某个task不会对被控制端做修改时但执行结果却显示是黄色的changed状态
可以通过 changed_when: false 关闭changed状态
执行命令完他会显示黄,这样可以显示绿
[root@ansible ansible]#cat test_changed.yml
---
- hosts: webserverstasks:- name: check sshd serviceshell: ps aux| grep sshdchanged_when: false #关闭changed状态

利用 changed_when 检查task返回结果
changed_when 检查task返回结果,决定是否继续向下执行

滚动执行
管理节点过多导致的超时问题解决方法
默认情况下,Ansible将尝试并行管理playbook中所有的机器。对于滚动更新用例,可以使用serial关键字定义Ansible一次应管理多少主机,还可以将serial关键字指定为百分比,表示每次并行执行的主机数占总数的比例
范例: 一次两台机器执行
#vim test_serial.yml
---
- hosts: allserial: 2 #每次只同时处理2个主机,将所有task执行完成后,再选下2个主机再执行所有task,直至所
有主机gather_facts: Falsetasks:- name: task onecommand: hostname- name: task twocommand: hostname
name: test serail
hosts: all
serial: "20%" #每次只同时处理20%的主机,主机数不足时,向下取整
委派至其它主机执行
利用委托技术,可以在非当前被控主机的其它主机上执行指定操作
注意: 当前执行的被管理端主机需要实现到被委派主机的ssh key 验证才能实现委派
范例: 将任务委派给指定的主机执行
[root@ansible ansible]#cat delegate.yml
#在10.0.0.8上执行hostname -I,而非当前主机localhost
- hosts: localhosttasks:- name: show ip addresscommand: hostname -Idelegate_to: 10.0.0.8 #指定当前任务被委派给的目标主机delegate_facts: true #收集被委派的目标主机的facts信息
范例: 将任务被委派给控制端ansible主机执行
#在本地执行ifconfig,而非10.0.0.8
[root@ansible ansible]#cat delegate2.yml
- hosts: 10.0.0.8tasks:- name: show ip addresslocal_action: command ifconfig #被委派给控制端ansible主机执行- name: show hostnameshell: hostnameconnection: local #被委派给控制端ansible主机执行- name: kernel versionshell: hostname -Idelegate_to: localhost #被委派给控制端ansible主机执行run_one: truce #委派任务只执行一次
只执行一次
利用 run_once 指令可以只执行一次,而非在所有被控主机都执行
root@ansible ~]#cat run_once.yml
- hosts: webservers
tasks:
- command: hostname
run_once: true[root@ansible ~]#ansible-playbook run_once.yml --list-hosts
playbook: run_once.yml
play #1 (webservers): webservers TAGS: []
pattern: ['webservers']
hosts (2):
10.0.0.8
10.0.0.7
[root@ansible ~]#ansible-playbook run_once.yml
环境变量
临时修改环境变量,只针对当前动作的task有效
[root@ansible ~]#cat environment.yml
- hosts: localhosttasks:- shell: echo $PATHenvironment:PATH: /usr/local/app/bin:{{ ansible_env.PATH }}
[root@ansible ~]#ansible-playbook environment.yml -v
Yaml 文件的相互调用
include
利用include 或 include_tasks 可以在某个task中调用其它的只有task内容的yaml文件
[root@ansible ansible]#cat a.yml
---
- hosts: webserverstasks:- name: run a jobcommand: wall run a job- name: excute b.ymlinclude: b.yml #调用另一个yaml文件#include_tasks: b.yml #另一种写法
[root@ansible ansible]#cat b.yml- name: run b jobcommand: wall run b job
import_playbook 由一个yml统一调用
还可以将多个包含完整内容的yml文件由一个yml统一调用
[root@ansible ansible]#cat main.yml
- import_playbook: tasks1.yml
- import_playbook: tasks2.yml[root@ansible ansible]#cat tasks1.yml
---
- hosts: webserverstasks:- name: run task1 jobcommand: wall run task1 job
[root@ansible ansible]#cat tasks2.yml
---
- hosts: dbserverstasks:- name: run task2 jobcommand: wall run task2 job
[root@ansible ansible]#ansible-play main.yml
Roles 角色
roles:多个角色的集合目录, 可以将多个的role,分别放至roles目录下的独立子目录中,如下示例
roles/
mysql/
nginx/
tomcat/
redis/
roles目录结构:
playbook1.yml
playbook2.yml
roles/
project1/
tasks/
files/
vars/
templates/
handlers/
defaults/
meta/
project2/
tasks/
files/
vars/
templates/
handlers/
defaults/
meta/
Roles各目录作用
roles/project/ :项目名称,有以下子目录
默认找mian.yml
- files/ :存放由copy或script模块等调用的文件
- templates/:template模块查找所需要模板文件的目录
- tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此
- 文件中通过include进行包含
- handlers/:至少应该包含一个名为main.yml的文件;此目录下的其它的文件需要在此文件中通过include进行包含
- vars/:定义变量,至少应该包含一个名为main.yml的文件;此目录下的其它的变量文件需要在此文件中通过include进行包含,也可以通过项目目录中的group_vars/all定义变量,从而实现角色通用代码和项目数据的分离
- meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文件需在此文件中通过include进行包含
- defaults/:设定默认变量时使用此目录中的main.yml文件,比vars的优先级低
相关文章:
Playbook的用法
目录 Playbook Playbook 与 Ad-Hoc 对比 YAML 语言特性 YAML语法简介 支持的数据类型 写法格式 1 scalar 标量 建议缩进两个空格,可多 2 Dictionary 字典 3 List 列表 三种常见的数据格式 Playbook 核心组件 不要用 tab 可以#注释 hosts remote_us…...
APP优化 —— MMAP内存映射
mmap 一种内存映射文件的方法 mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中作用很大。 头文件 <sys/mman.h> 函数原型 v…...
paddle.vision 与 torchvision 中的box NMS使用方式
torchvision 中有多个用于计算 BBox NMS 的 API, 在本篇氵文中, 使用 torchvision.ops.boxes.batched_nmspaddle.vision 中通过 paddle.vision.ops.nms 来进行多个 Box 的 NMS 操作 1. torchvision 中 batched_nms 操作 torchvision batched_nms def batched_nms(boxes: to…...
php mysql校园帮忙领取快递平台
1、后台管理员用户名hsg 密码hsg 2、开发语言:PHP,数据库为MySql 3、数据库连接字符串在conn.php中修改 4、运行环境wamp5.1.7或者appserv2.5.9 5.程序编码gbk.不支持php5.3以上版本 6.本人发布的程序一律享有免费运行一次…...
C/C++开发,无可避免的内存管理(篇二)-约束好跳脱的内存
一、养成内存管理好习惯 1.1 养成动态对象创建、调用及释放好习惯 开发者手动接管内存分配时,必须处理这两个任务。分配原始内存时,必须在该内存中构造对象;在释放该内存之前,必须保证适当地撤销这些对象。如果你的项目是c项目&am…...
【Java】让我们对多态有深入的了解(九)
目录 (1)接口的基本介绍编辑 (2)接口的注意事项和细节 1.接口不能被实例化 2.接口中所有方法是public方法,接口中的抽象方法,可以不用abstract修饰 3.一个普通类实现接口,必须将接口所有…...
12 个适合做外包项目的开源后台管理系统
1.D2admin 开源地址:https://github.com/d2-projects/d2-admin 文档地址:https://d2.pub/zh/doc/d2-admin/ 效果预览:https://d2.pub/d2-admin/preview/#/index 开源协议:MIT 2.vue-element-admin 开源地址:https…...
鼠标更换指针图案和更改typora的主题
鼠标更换指针图案 由此偶然看见好几个朋友都使用了新的图案替换掉了原有的鼠标图案,今天寻思自己也换一个图案 主要是觉得鼠标大一点儿会好看一些,所以就找了一些教程 官方教程,小的变动 当然最多的是官方教程,如果你只是想要…...
【洛谷 P1563】[NOIP2016 提高组] 玩具谜题(模拟+结构体数组+指针)
[NOIP2016 提高组] 玩具谜题 题目背景 NOIP2016 提高组 D1T1 题目描述 小南有一套可爱的玩具小人, 它们各有不同的职业。 有一天, 这些玩具小人把小南的眼镜藏了起来。 小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的面朝圈外。如下图: 这时 singer 告诉小南一个谜…...
阿里测试经验7年,从功能测试到自动化测试,我整理的超全学习指南
做测试七年多,有不少人问过我下面问题: 现在的手工测试真的不行了吗? 测试工程师,三年多快四年的经验,入门自动化测试需要多久? 自学自动化测试到底需要学哪些东西? 不得不说,随着…...
Educational Codeforces Round 143 (Rated for Div. 2)
Educational Codeforces Round 143 (Rated for Div. 2) D. Triangle Coloring 思路: 每个环都需要取最大值,那么我们讨论一个环获得最大值选的两条边的可能取法: 显然:如果三边相等,这个环有3种取法。如…...
业务代码编写过程中如何「优雅的」配置隔离
思考 不同的处理方式 1.常规的处理方式,通过某种规则判断区分代码环境 // 获取环境标识 const env getCurrentEnv();if (env dev) {// do something } else if (env test) {// do something } else if (env prod) {// do something } 分析: 1.此种…...
English Learning - L2-2 英音地道语音语调 2023.02.23 周四
English Learning - L2-2 英音地道语音语调 2023.02.23 周四查音标的工具怎么练习效果好准备工作大小声练习大元音开口度的对比舌位对比复习后元音 /ɑː/ /ɔː/ /uː//ɑː//ɔː//uː/前元音 /iː/发音技巧对应单词的发音对应句子的发音常见的字母组合中元音 /ɜː/发音技巧…...
java:线程等待与唤醒 - Object的wait()和notify()
java:线程等待与唤醒 - Object的wait()和notify() 1 前言 java使用Object类的wait()和notify()方法,可以实现线程等待和唤醒(Object类为所有类的父类,即所有类天然具有线程等待和唤醒的方法,一般使用Object类的wait(…...
实现弹窗功能并修改其中一个系数
把鼠标放在number-info上面,会是一个delon/chart的类库,可以在NG-ALAIN上找到阅读NG ALAIN的图表,以及number-info样式,数据文本 它拥有[title] [subtitle]两个可以是TemplateRef类型的,而template可以在里面放一些东西,比如按钮,所以可以放一个修改按钮 这里刚开始把template放…...
vue-draggable浏览器拖拽event事件对象拖动时 DragEvent path undefined
场景: 在做组件拖拽过程中,需要获取到触发元素冒泡过程中的所有元素,所以使用了event.path属性。在Chrome下正常运行,但是在FireFox下测试时发现,完犊子,失效了,通过问题排查,发现了…...
【云原生】搭建k8s高可用集群—20230225
文章目录多master(高可用)介绍高可用集群使用技术介绍搭建高可用k8s集群步骤1. 准备环境-系统初始化2. 在所有master节点上部署keepalived3.1 安装相关包3.2 配置master节点3.3 部署haproxy错误解决3. 所有节点安装Docker/kubeadm/kubelet4. 部署Kuberne…...
LeetCode121_121. 买卖股票的最佳时机
LeetCode121_121. 买卖股票的最佳时机 一、描述 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最…...
收割不易,五面Alibaba终拿Java岗offer
前言 前段时间有幸被阿里的一位同学内推,参加了阿里巴巴Java岗位的面试,本人19年双非本科软件工程专业,目前有一年半的工作经验,面试前就职于一家外包公司。如果在自己本人拿到offer之前,如果有人告诉我一年工作经验可…...
【离线数仓-4-数据仓库设计-分层规划构建流程】
离线数仓-4-数据仓库设计-分层规划&构建流程离线数仓-4-数据仓库设计-分层规划&构建流程1.数据仓库分层规划2.数据仓库构建流程1.数据调研1.业务调研2.需求分析3.总结2.明确数据域3.构建业务总线矩阵&维度模型设计4.明确统计指标1.指标体系相关概念1.原子指标2.派生…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...
