Ansible playbook 详解与实战操作
一、概述
-
playbook
与ad-hoc
相比,是一种完全不同的运用 ansible 的方式,类似与 saltstack 的 state 状态文件。ad-hoc 无法持久使用,playbook 可以持久使用。 -
playbook
是由一个或多个 play 组成的列表,play 的主要功能在于将事先归并为一组的主机装扮成事先通过 ansible 中的 task 定义好的角色。 -
从根本上来讲,所谓的 task 无非是调用 ansible 的一个 module。将多个 play 组织在一个 playbook 中,即可以让它们联合起来按事先编排的机制完成某一任务。
参考文档:https://ansible-tran.readthedocs.io/en/latest/docs/playbooks.html
Ansible 的基础介绍和环境部署可以参考这篇文章:
二、playbook 核心元素
-
Hosts
执行的远程主机列表 -
Tasks
任务集 -
Varniables
内置变量或自定义变量在 playbook 中调用 -
Templates
模板,即使用模板语法的文件,比如配置文件等 -
Handlers
和 notity 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行 -
Tags
标签,指定某条任务执行,用于选择运行 playbook 中的部分代码。
三、playbook 语法(yaml)
-
playbook 使用
yaml
语法格式,后缀可以是yaml
,也可以是yml
。 -
YAML( /ˈjæməl/ )参考了其他多种语言,包括:XML、C 语言、Python、Perl 以及电子邮件格式 RFC2822,Clark Evans 在 2001 年 5 月在首次发表了这种语言,另外 Ingy döt Net 与 OrenBen-Kiki 也是这语言的共同设计者。
-
YAML 格式是类似 JSON 的文件格式。YAML 用于文件的配置编写,JSON 多用于开发设计。
1)YAML 介绍
1、YAML 格式如下
-
文件的第一行应该以“---”(三个连字符)开始,表明 YAML 文件的开始。
-
在同一行中,#之后的内容表示注释,类似于 shell,python 和 ruby。
-
YAML 中的列表元素以“-”开头并且跟着一个空格。后面为元素内容。
-
同一个列表之中的元素应该保持相同的缩进,否则会被当做错误处理。
-
play 中 hosts、variables、roles、tasks 等对象的表示方法都是以键值中间以“:”分隔表示,并且“:”之后要加一个空格。
2、playbooks yaml 配置文件解释
Hosts:运行指定任务的目标主机
remoute_user:在远程主机上执行任务的用户;
sudo_user:
tasks:任务列表tasks的具体格式:tasks:- name: TASK_NAMEmodule: argumentsnotify: HANDLER_NAMEhandlers:- name: HANDLER_NAMEmodule: arguments##模块,模块参数:
格式如下:(1)action: module arguments(2) module: arguments
注意:shell和command模块后直接加命令,而不是key=value类的参数列表handlers:任务,在特定条件下触发;接受到其他任务的通知时被触发;
3、示例
---
- hosts: webremote_user: roottasks:- name: install nginx ##安装模块,需要在被控主机里加上nginx的源yum: name=nginx state=present- name: copy nginx.conf ##复制nginx的配置文件过去,需要在本机的/tmp目录下编辑nginx.confcopy: src=/tmp/nginx.conf dest=/etc/nginx/nginx.conf backup=yesnotify: reload #当nginx.conf发生改变时,通知给相应的handlerstags: reloadnginx #打标签- name: start nginx service #服务启动模块service: name=nginx state=startedtags: startnginx #打标签handlers:- name: reloadservice: name=nginx state=restarted
2)variables 变量
variables 变量有四种定义方法。如下:
1、facts:可以直接调用
ansible 中有 setup 模块,这个模块就是通过 facts 组件来实现的,主要是节点本身的一个系统信息,bios 信息,网络,硬盘等等信息。这里的 variables 也可以直接调用 facts 组件的 facters 我们可以使用setup
模块来获取,然后直接放入我们的剧本之中调用即可。
ansible web -m setup
常用的几个参数:
ansible_all_ipv4_addresses # ipv4的所有地址
ansible_all_ipv6_addresses # ipv6的所有地址
ansible_date_time # 获取到控制节点时间
ansible_default_ipv4 # 默认的ipv4地址
ansible_distribution # 系统
ansible_distribution_major_version # 系统的大版本
ansible_distribution_version # 系统的版本号
ansible_domain #系统所在的域
ansible_env #系统的环境变量
ansible_hostname #系统的主机名
ansible_fqdn #系统的全名
ansible_machine #系统的架构
ansible_memory_mb #系统的内存信息
ansible_os_family # 系统的家族
ansible_pkg_mgr # 系统的包管理工具
ansible_processor_cores #系统的cpu的核数(每颗)
ansible_processor_count #系统cpu的颗数
ansible_processor_vcpus #系统cpu的总个数=cpu的颗数*CPU的核数
ansible_python # 系统上的python
搜索
ansible web -m setup -a 'filter=*processor*'
2、用户自定义变量
自定义变量有两种方式
-
通过命令行传入
ansible-playbook命令行中的 -e VARS,--extra-vars VARS,这样就可以直接把自定义的变量传入
使用 playbook 定义变量,实例如下:
---
- hosts: webremote_user: roottasks:- name: install {{ rpmname }}yum: name={{ rpmname }} state=present- name: copy {{ rpmname }}.confcopy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yesnotify: reloadtags: reload{{ rpmname }}- name: start {{ rpmname }} serviceservice: name={{ rpmname }} state=startedtags: start{{ rpmname }}handlers:- name: reloadservice: name={{ rpmname }} state=restarted
使用:
ansible-playbook nginx.yml -e rpmname=keepalived
ansible-playbook nginx.yml --extra-vars rpmname=keepalived
-
在 playbook 中定义变量
##在playbook中定义变量如下:
vars:- var1: value1- var2: value2
使用:
---
- hosts: webremote_user: rootvars:- rpmname: keepalivedtasks:- name: install {{ rpmname }}yum: name={{ rpmname }} state=present- name: copy {{ rpmname }}.confcopy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yesnotify: reloadtags: reload{{ rpmname }}- name: start {{ rpmname }} serviceservice: name={{ rpmname }} state=startedtags: start{{ rpmname }}handlers:- name: reloadservice: name={{ rpmname }} state=restarted
3、通过 roles 传递变量
下面介绍 roles 会使用 roles 传递变量,小伙伴可以翻到下面看详解讲解。
4、 Host Inventory
可以在主机清单中定义,方法如下:
#向不同的主机传递不同的变量
IP/HOSTNAME varaiable=value var2=value2#向组中的主机传递相同的变量
[groupname:vars]
variable=value
3)流程控制
1、用 when 来表示的条件判断
- hosts: webremote_user: root#代表用root用户执行,默认是root,可以省略tasks:- name: createfilecopy: content="test3" dest=/opt/p1.ymlwhen: a=='3'- name: createfilecopy: content="test4" dest=/opt/p1.ymlwhen: a=='4'
如果 a"3",就将“test3”,写入到 web 组下被管控机的/opt/p1.yml 中,
如果 a"4",就将“test4”,写入到 web 组下被管控机的/opt/p1.yml 中。
执行
# 语法校验
ansible-playbook --syntax-check p1.yml#执行
ansible-playbook -e 'a="3"' p1.yml
2、标签(只执行配置文件中的一个任务)
- hosts: webtasks:- name: installnginxyum: name=nginx- name: copyfilecopy: src=/etc/nginx/nginx.conf dest=/etc/nginx/nginx.conftags: copyfile- name: startservice: name=nginx static=restarted
执行
# 语法校验
ansible-playbook --syntax-check p2.yml#执行
ansible-playbook -t copyfile p2.yml
3、循环 with_items
创建三个用户
- hosts: webtasks:- name: createruseruser: name={{ item }}with_items:- shy1- shy2- shy3- name: creategroupgroup: name={{ item }}with_items:- group1- group2- group3
执行
#语法校验
ansible-playbook --syntax-check p3.yml#执行
ansible-playbook p3.yml
4、循环嵌套(字典)
用户 shy1 的属组是 group1,用户 shy2 的属组是 group2,用户 shy3 的属组是 group3
- hosts: webtasks:- name: creategroupgroup: name={{item}}with_items:- group3- group4- group5- name: createuseruser: name={{item.user}} group={{item.group}}with_items:- {'user': shy3,'group': group3}- {'user': shy4,'group': group4}- {'user': shy5,'group': group5}
执行
#语法校验
ansible-playbook --syntax-check p4.yml#执行
ansible-playbook p4.yml
4)模板 templates
-
模板是一个文本文件,嵌套有脚本(使用模板编程语言编写)
-
Jinja2 是 python 的一种模板语言,以 Django 的模板语言为原本
该模板支持:
字符串:使用单引号或双引号;数字:整数,浮点数;列表:[item1, item2, ...]元组:(item1, item2, ...)字典:{key1:value1, key2:value2, ...}布尔型:true/false算术运算:+, -, *, /, //, %, **比较操作:==, !=, >, >=, <, <=逻辑运算:and, or, not
-
通常模板都是通过引用变量来运用的
【示例】
1、定义模板
user nginx; #设置nginx服务的系统使用用户
worker_processes {{ ansible_processor_vcpus }}; #工作进程数error_log /var/log/nginx/error.log warn; #nginx的错误日志
pid /var/run/nginx.pid; #nginx启动时候的pidevents {worker_connections 1024; #每个进程允许的最大连接数
}http { #http请求配置,一个http可以包含多个server#定义 Content-Typeinclude /etc/nginx/mime.types;default_type application/octet-stream;#日志格式 此处main与access_log中的main对应#$remote_addr:客户端地址#$remote_user:http客户端请求nginx认证的用户名,默认不开启认证模块,不会记录#$timelocal:nginx的时间#$request:请求method + 路由 + http协议版本#status:http reponse 状态码#body_bytes_sent:response body的大小#$http_referer:referer头信息参数,表示上级页面#$http_user_agent:user-agent头信息参数,客户端信息#$http_x_forwarded_for:x-forwarded-for头信息参数log_format main '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';#访问日志,后面的main表示使用log_format中的main格式记录到access.log中access_log /var/log/nginx/access.log main;#nginx的一大优势,高效率文件传输sendfile on;#tcp_nopush on;#客户端与服务端的超时时间,单位秒keepalive_timeout 65;#gzip on;server { #http服务,一个server可以配置多个locationlisten {{ nginxport }}; #服务监听端口server_name localhost; #主机名、域名#charset koi8-r;#access_log /var/log/nginx/host.access.log main;location / {root /usr/share/nginx/html; #页面存放目录index index.html index.htm; #默认页面}#error_page 404 /404.html;# 将500 502 503 504的错误页面重定向到 /50x.htmlerror_page 500 502 503 504 /50x.html;location = /50x.html { #匹配error_page指定的页面路径root /usr/share/nginx/html; #页面存放的目录}# proxy the PHP scripts to Apache listening on 127.0.0.1:80##location ~ \.php$ {# proxy_pass http://127.0.0.1;#}# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000##location ~ \.php$ {# root html;# fastcgi_pass 127.0.0.1:9000;# fastcgi_index index.php;# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;# include fastcgi_params;#}# deny access to .htaccess files, if Apache's document root# concurs with nginx's one##location ~ /\.ht {# deny all;#}}include /etc/nginx/conf.d/*.conf;
}
2、定义 yaml 编排
---
- hosts: webremote_user: rootvars:- rpmname: nginx- nginxport: 8088tasks:- name: install {{ rpmname }}yum: name={{ rpmname }} state=present- name: copy {{ rpmname }}.confcopy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yesnotify: reloadtags: reload{{ rpmname }}- name: start {{ rpmname }} serviceservice: name={{ rpmname }} state=startedtags: start{{ rpmname }}handlers:- name: reloadservice: name={{ rpmname }} state=restarted
使用
##使用reloadnginx标签,重新加载剧本
ansible-playbook nginx.yml -t reloadnginx
copy 与 template 的区别
-
copy 模块不替代参数,template 模块替代参数
-
template 的参数几乎与 copy 的参数完全相同
5)handlers(触发事件)
notify:触发
handlers:触发的动作
使用上场景:修改配置文件时
【示例】 正常情况时 handlers 是不会执行的
- hosts: webtasks:- name: installredisyum: name=redis- name: copyfiletemplate: src=redis.conf dest=/etc/redis.conftags: copyfilenotify: restart- name: startservice: name=redis state=startedhandlers:- name: restartservice: name=redis
执行
ansible-playbook -t copyfile p6.yml
6)roles
1、roles 介绍与优势
一般情况下将 roles 写在**/etc/ansible/roles**中,也可以写在其他任意位置(写在其他位置要自己手动建立一个 roles 文件夹)
-
对于以上所有方式有个缺点就是无法实现同时部署 web、database、keepalived 等不同服务或者不同服务器组合不同的应用就需要写多个 yaml 文件,很难实现灵活的调用
-
roles 用于层次性,结构化地组织 playbook。roles 能够根据层次结果自动装载变量文件、tasks 以及 handlers 等。
-
要使用 roles 只需要在 playbook 中使用 include 指令即可。
-
简单来讲,roles 就是通过分别将变量(vars)、文件(files)、任务(tasks)、模块(modules)以及处理器(handlers)放置于单独的目录中,并且可以便捷的 include 它们地一种机制。
-
角色一般用于基于主机构建服务的场景中,但是也可以用于构建守护进程等场景中。
2、目录结构
创建目录
mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
-
roles/
-
mysql/:mysql 服务的 yml 文件
-
httpd/:apached 服务的 yml 文件
-
nginx/:nginx 服务的 yml 文件
-
files/
:存储由 copy 或者 script 等模块调用的文件或者脚本; -
tasks/
:此目录中至少应该有一个名为main.yml的文件,用于定义各个 task;其他文件需要由main.yml进行包含调用; -
handlers/
:此目录中至少应该有一个名为main.yml的文件,用于定义各个 handler;其他文件需要由 main.yml 进行包含调用; -
vars/
:此目录至少应该有一个名为main,yml的文件,用于定义各个 variable;其他的文件需要由main.yml进行包含调用; -
templates/
:存储由 templates 模块调用的模板文件; -
meta/
:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定以及依赖关系,其他文件需要由main.yml进行包含调用; -
default/
:此目录至少应该有一个名为main.yml的文件,用于设定默认变量;
3、实战操作
【1】创建目录
mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
【2】定义配置文件
先下载 nginx rpm 部署包
# 下载地址:http://nginx.org/packages/centos/7/x86_64/RPMS/wget http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.18.0-1.el7.ngx.x86_64.rpm -O nginx/files/nginx-1.18.0-1.el7.ngx.x86_64.rpm
-
nginx/tasks/main.yml
- name: cpcopy: src=nginx-1.18.0-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm
- name: installyum: name=/tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm state=latest
- name: conftemplate: src=nginx.conf.j2 dest=/etc/nginx/nginx.conftags: nginxconfnotify: new conf to reload
- name: start serviceservice: name=nginx state=started enabled=true
- nginx/templates/nginx.conf.j2
user nginx; #设置nginx服务的系统使用用户
worker_processes {{ ansible_processor_vcpus }}; #工作进程数error_log /var/log/nginx/error.log warn; #nginx的错误日志
pid /var/run/nginx.pid; #nginx启动时候的pidevents {worker_connections 1024; #每个进程允许的最大连接数
}http { #http请求配置,一个http可以包含多个server#定义 Content-Typeinclude /etc/nginx/mime.types;default_type application/octet-stream;#日志格式 此处main与access_log中的main对应#$remote_addr:客户端地址#$remote_user:http客户端请求nginx认证的用户名,默认不开启认证模块,不会记录#$timelocal:nginx的时间#$request:请求method + 路由 + http协议版本#status:http reponse 状态码#body_bytes_sent:response body的大小#$http_referer:referer头信息参数,表示上级页面#$http_user_agent:user-agent头信息参数,客户端信息#$http_x_forwarded_for:x-forwarded-for头信息参数log_format main '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';#访问日志,后面的main表示使用log_format中的main格式记录到access.log中access_log /var/log/nginx/access.log main;#nginx的一大优势,高效率文件传输sendfile on;#tcp_nopush on;#客户端与服务端的超时时间,单位秒keepalive_timeout 65;#gzip on;server { #http服务,一个server可以配置多个locationlisten {{ nginxport }}; #服务监听端口server_name localhost; #主机名、域名#charset koi8-r;#access_log /var/log/nginx/host.access.log main;location / {root /usr/share/nginx/html; #页面存放目录index index.html index.htm; #默认页面}#error_page 404 /404.html;# 将500 502 503 504的错误页面重定向到 /50x.htmlerror_page 500 502 503 504 /50x.html;location = /50x.html { #匹配error_page指定的页面路径root /usr/share/nginx/html; #页面存放的目录}# proxy the PHP scripts to Apache listening on 127.0.0.1:80##location ~ \.php$ {# proxy_pass http://127.0.0.1;#}# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000##location ~ \.php$ {# root html;# fastcgi_pass 127.0.0.1:9000;# fastcgi_index index.php;# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;# include fastcgi_params;#}# deny access to .htaccess files, if Apache's document root# concurs with nginx's one##location ~ /\.ht {# deny all;#}}include /etc/nginx/conf.d/*.conf;
}
-
nginx/vars/main.yml
nginxport: 9999
-
nginx/handlers/main.yml
- name: new conf to reloadservice: name=nginx state=restarted
-
定义剧本文件(roles.yml)
- hosts: webremote_user: rootroles:- nginx
最后的目录结构如下:
执行
ansible-playbook roles.yml
到这里一个完整版的 roles 演示示例就完成了,接下来也会真正使用 ansible playbook roles 应用到真实场景中
相关文章:

Ansible playbook 详解与实战操作
一、概述 playbook 与 ad-hoc 相比,是一种完全不同的运用 ansible 的方式,类似与 saltstack 的 state 状态文件。ad-hoc 无法持久使用,playbook 可以持久使用。 playbook 是由一个或多个 play 组成的列表,play 的主要功能在于将事先归并为一…...

青少年夏令营管理系统的设计与开发(社团管理)(springboot+vue)+文档
💗博主介绍💗:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示:文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…...

加速合并,音频与字幕的探讨
因上一节。合并时速度太慢了。显卡没用上。所以想快一点。1分钟的视频用了5分钟。 在合并视频时,进度条中的 now=None 通常表示当前处理的时间点没有被正确记录或显示。这可能是由于 moviepy 的内部实现细节或配置问题。为了加快视频合并速度并利用 GPU 加速,可以采取以下措…...

Uniapp插件如何通过NFC读取多种证卡信息?
nfc读卡uniapp插件,由中软高科进行开发,主要是通过NFC读取居民身份证、港澳台居住证、外国人居住证、护照等证卡的信息。经过多个版本的升级更新,目前性能已趋于稳定,并且读卡速度较之最初版本有了大的提升。 注意事项 测试使用的…...

米哈游C++开发精选60道面试题及参考答案
C++ 面向对象的三个特征 封装是把数据和操作数据的函数捆绑在一起,并且对数据的访问进行限制。这样做的好处是可以隐藏对象的内部实现细节,只暴露必要的接口给外部。例如,在一个银行账户类中,账户余额这个数据成员是被封装起来的,外部不能直接访问和修改,而是通过存款、取…...

深度与视差的关系及其转换
深度与视差的关系及其转换 在计算机视觉和立体视觉中,深度和视差是两个重要的概念。理解这两者之间的关系对于实现立体图像处理、三维重建以及深度估计至关重要。在这篇博客中,我们将深入探讨深度和视差的概念,并介绍它们之间的转换关系。 …...

安全见闻全解析
跟随 泷羽sec团队学习 声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及…...

搭建Tomcat(四)---Servlet容器
目录 引入 Servlet容器 一、优化MyTomcat ①先将MyTomcat的main函数搬过来: ②将getClass()函数搬过来 ③创建容器 ④连接ServletConfigMapping和MyTomcat 连接: ⑤完整的ServletConfigMapping和MyTomcat方法: a.ServletConfigMappin…...

PT2044A 单触控单输出IC
1 产品概述 ● PT2044A 是一款单通道触摸检测芯片。该芯片内建稳压电路,提供稳定电压给触摸感应电路使用。同时内部集成高效完善的触摸检测算法,使得芯片具有稳定的触摸检测效果。该芯片专为取代传统按键而设计,具有宽工作电压与低功耗的特性…...

docker安装mysql5.7
1、宿主机创建映射目录 mkdir -p /data/mysql/log mkdir -p /data/mysql/data mkdir -p /data/mysql/conf这里我放在了/data/mysql目录下 2、拉取mysql镜像 docker pull mysql:5.7注意是5.7版本,如果是8版本操作会略有不同,下篇文章介绍安装8版本的操…...

安卓 文件管理相关功能记录
文件管理细分为图片、视频、音乐、文件四类 目录 权限 静态声明权限 动态检查和声明权限方法 如何开始上述动态申请的流程 提示 图片 获取图片文件的对象列表 展示 删除 视频 获取视频文件的对象列表 获取视频file列表 按日期装载视频文件列表 展示 播放 删除…...

GB28181系列三:GB28181流媒体服务器ZLMediaKit
我的音视频/流媒体开源项目(github) GB28181系列目录 目录 一、ZLMediaKit介绍 二、 ZLMediaKit安装、运行(Ubuntu) 1、安装 2、运行 3、配置 三、ZLMediaKit使用 一、ZLMediaKit介绍 ZLMediaKit是一个基于C11的高性能运营级流媒体服务框架,项目地址…...

ScottPlot学习的常用笔记
ScottPlot学习的常用笔记 写在前面版本的选择第一个障碍:版本问题。 ScottPlot4.0的官方网站与示例官方起始页cookbook5.0Demo4.1 demo以4.1为例,解压和运行如下: 下载源代码和编译先说结论: 写在前面 之前调研的TraceCompass&am…...

二、mapbox-gl实现白膜立体建筑
有时候我们只有二维的面数据,怎么实现类似高德地图中的白膜立体建筑呢?在mapbox-gl中很容易实现,具体如下。 要在Vue中结合Mapbox显示自定义的GeoJSON数据,并实现建筑物的白膜效果,我们需要执行以下步骤: …...

mybatisplus 分库查询
mybatisplus 分库查询 比如我们的项目有两个数据库 不同的表在不同的库 我们是可以使用mybatisplus来实现 首选引入pom <dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><vers…...

计算属性 (vue3)
二 实例 1route.query.type...

RabbitMQ 安装、配置和使用介绍 使用前端js直接调用方式
1. 安装 RabbitMQ 1.1 安装 Erlang RabbitMQ 是基于 Erlang 语言开发的,因此首先需要安装 Erlang。 在 Ubuntu 上安装 Erlang: bash sudo apt-get update sudo apt-get install erlang 在 CentOS 上安装 Erlang: bash sudo yum insta…...

电脑显示器选购指南2024
选择显示器是五花八门的显示参数,如何选择,以下给出参数说明,及部分参考: 1. 尺寸和分辨率 尺寸(英寸) 根据使用距离和用途选择合适的屏幕尺寸: 21-24 英寸:适合小桌面空间、日常…...

vue2中如何实现自定义指令
实现自动聚焦功能 1.不用自定义指令 使用生命周期钩子mounted 2.使用自定义指令 1. 使用全局组件 首先在main.js中注册 然后在组件中直接使用v-指令名 2. 使用局部注册 局部注册和全局注册类似 如果很多组件需要自定义,建议使用自定义指令注册在全局...

QT从入门到精通(一)——Qlabel介绍与使用
1. QT介绍——代码测试 Qt 是一个跨平台的应用程序开发框架,广泛用于开发图形用户界面(GUI)应用程序,也支持非图形应用程序的开发。Qt 提供了一套工具和库,使得开发者能够高效地构建高性能、可移植的应用程序。以下是…...

【jpa】springboot使用jpa示例
目录 1. 请求示例2. pom依赖3. application.yaml4.controller5. service6. repository7. 实体8. 启动类 1. 请求示例 curl --location --request POST http://127.0.0.1:8080/user \ --header User-Agent: Apifox/1.0.0 (https://apifox.com) \ --header Content-Type: applic…...

Python Flask Web框架快速入门
Flask 入门Demo Flask 开发环境搭建,执行如下指令: pip install flask# 第一节: Flask 快速入门from flask import Flask app Flask(__name__)app.route(/flask) def hello_flask():return Hello Flaskapp.run()核心代码剖析: 从flask包导…...

ansible自动化运维(五)roles角色管理
目录 Roles角色管理 创建nginx的角色目录 定义任务配置文件: 定义jinjia2模板: 定义nginx yml文件 检查语法,执行命令 检验结果: Roles角色管理 角色(roles)是ansible自1.2版本开始引入的新特性&…...

前端学习一
一 进程与线程 线程是进程执行的最小单位,进程是系统分配任务的最小单位。 一个进程可执行最少一个线程。线程分为子线程和主线程。 主线程关闭则子线程关闭。 二 浏览器进程 浏览器是多进程多线程应用。 进程包括: 浏览器进程 负责程序交互渲染…...

【OSS】php使用oss存储
阿里云oss官方文档:文档 1、前期工作 创建阿里云账号,登录创建bucket,注意修改权限,要不然可能读取不到 申请accessKeyId和accessKeySecret accessKey 2、项目中安装OSS扩展 composer require aliyuncs/oss-sdk-php3、基础使…...

UE5 C+、C++、C# 构造方法区别示例
我们对比一下UE C、C 、C#的构造方法: 1. UE4 C例子: // 声明和构造合并在一起static ConstructorHelpers::FObjectFinder<UTexture2D> CrosshairTexObj(TEXT("/Game/Path"));// 使用加载的资源UTexture2D* Texture CrosshairTexObj.…...

leetcode-146.LRU缓存(易理解)
为了实现一个满足 LRU(最近最少使用)缓存约束的数据结构,我们需要在 (O(1)) 时间复杂度内完成 get 和 put 操作。这通常可以通过结合使用哈希表和双向链表来实现: 哈希表:用于在 (O(1)) 时间复杂度内实现对缓存中元素…...

JavaSe部分总结
我们先来了解一下Java语言,JavaSE是Java编程语言的标准版,主要是来学习Java的基本语法,书写方式,以及一些简单的逻辑循环和判断,包括一些关键字,特殊类(抽象类),特殊的方法(static修饰的方法,final修饰的方法)等等,最重要的是Java语言是比较C语言和C语言是比较简单的,Java是面向…...

iPhone批量删除照片的方法
对于每一个iPhone用户来说,照片管理是一项日常而重要的任务。随着时间的积累,无数的照片快速填满了我们的存储空间,从美丽的风景到重要的家庭聚会,每一张照片都记录着我们生活中的瞬间。然而,当存储空间即将耗尽时&…...

红日靶场vulnstack 7靶机的测试报告[细节](一)
目录 一、测试环境 1、系统环境 2、注意事项 3、使用工具/软件 二、测试目的 三、操作过程 1、信息搜集 2、Redis未授权访问漏洞获取web1靶机系统权限 3、获取docker靶机系统权限 ①Laravel框架漏洞利用getshell ②Laravel主机的提权&&docker容器逃逸 提权…...