Ansible playbook 讲解与实战操作

news2024/11/18 20:25:44

文章目录

    • 一、概述
    • 二、playbook 核心元素
    • 三、playbook 语法(yaml)
      • 1)YAML 介绍
        • 1、YAML 格式如下
        • 2、playbooks yaml配置文件解释
        • 3、示例
      • 2)variables 变量
        • 1、facts:可以直接调用
        • 2、用户自定义变量
        • 3、通过roles传递变量
        • 4、 Host Inventory
      • 3)流程控制
        • 1、用when 来表示的条件判断
        • 2、标签(只执行配置文件中的一个任务)
        • 3、循环 with_items
        • 4、循环嵌套(字典)
      • 4)模板 templates
      • 5)handlers(触发事件)
      • 6)roles
        • 1、roles介绍与优势
        • 2、目录结构
        • 3、实战操作

一、概述

  • playbookad-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 的基础介绍和环境部署可以参考我这篇文章: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_NAME
    module: arguments
    notify: HANDLER_NAME
    handlers:
  - name: HANDLER_NAME
    module: arguments
 
##模块,模块参数:
格式如下:
    (1)action: module arguments
     (2) module: arguments
注意:shell和command模块后直接加命令,而不是key=value类的参数列表
 
 
handlers:任务,在特定条件下触发;接受到其他任务的通知时被触发;

3、示例

---
- hosts: web
  remote_user: root
  tasks:
    - name: install nginx        ##安装模块,需要在被控主机里加上nginx的源
      yum: name=nginx state=present
    - name: copy nginx.conf    ##复制nginx的配置文件过去,需要在本机的/tmp目录下编辑nginx.conf
      copy: src=/tmp/nginx.conf dest=/etc/nginx/nginx.conf backup=yes
      notify: reload    #当nginx.conf发生改变时,通知给相应的handlers
      tags: reloadnginx    #打标签
    - name: start nginx service    #服务启动模块
      service: name=nginx state=started
      tags: startnginx    #打标签

  handlers:
    - name: reload
      service: 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: web
  remote_user: root
  tasks:
  
    - name: install {{ rpmname }}
      yum: name={{ rpmname }} state=present
    - name: copy {{ rpmname }}.conf
      copy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
      notify: reload
      tags: reload{{ rpmname }}
    - name: start {{ rpmname }} service
      service: name={{ rpmname }} state=started
      tags: start{{ rpmname }}
 
  handlers:
    - name: reload
      service: 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: web
  remote_user: root
  vars:
    - rpmname: keepalived
  tasks:
    - name: install {{ rpmname }}
      yum: name={{ rpmname }} state=present
    - name: copy {{ rpmname }}.conf
      copy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
      notify: reload
      tags: reload{{ rpmname }}
    - name: start {{ rpmname }} service
      service: name={{ rpmname }} state=started
      tags: start{{ rpmname }}
 
  handlers:
    - name: reload
      service: 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: web
  remote_user: root#代表用root用户执行,默认是root,可以省略
  tasks:
  - name: createfile
    copy: content="test3" dest=/opt/p1.yml
    when: a=='3'
  - name: createfile
    copy: content="test4" dest=/opt/p1.yml
    when: 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: web
  tasks:
  - name: installnginx
    yum: name=nginx
  - name: copyfile
    copy: src=/etc/nginx/nginx.conf dest=/etc/nginx/nginx.conf
    tags: copyfile
  - name: start
    service: name=nginx static=restarted

执行

# 语法校验
ansible-playbook  --syntax-check p2.yml

#执行
ansible-playbook -t copyfile p2.yml 

3、循环 with_items

创建三个用户

- hosts: web
  tasks:
  - name: createruser
    user: name={{ item }}
    with_items:
    - shy1
    - shy2
    - shy3
  - name: creategroup
    group: 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: web
  tasks:
  - name: creategroup
    group: name={{item}}
    with_items:
    - group3
    - group4
    - group5
  - name: createuser
    user: 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启动时候的pid

events {
    worker_connections  1024; #每个进程允许的最大连接数
}

http { #http请求配置,一个http可以包含多个server

    #定义 Content-Type
    include       /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可以配置多个location
        listen       {{ 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.html
        error_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: web
  remote_user: root
  vars:
    - rpmname: nginx
    - nginxport: 8088
  tasks:
    - name: install {{ rpmname }}
      yum: name={{ rpmname }} state=present
    - name: copy {{ rpmname }}.conf
      copy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes
      notify: reload
      tags: reload{{ rpmname }}
    - name: start {{ rpmname }} service
      service: name={{ rpmname }} state=started
      tags: start{{ rpmname }}
 
  handlers:
    - name: reload
      service: name={{ rpmname }} state=restarted

使用

##使用reloadnginx标签,重新加载剧本
ansible-playbook nginx.yml -t reloadnginx

copy与template的区别

  • copy模块不替代参数,template模块替代参数
  • template的参数几乎与copy的参数完全相同

5)handlers(触发事件)

notify:触发
handlers:触发的动作

使用上场景:修改配置文件时

【示例】 正常情况时handlers是不会执行的

- hosts: web
  tasks:
  - name: installredis
    yum: name=redis
  - name: copyfile
    template: src=redis.conf dest=/etc/redis.conf
    tags: copyfile
    notify: restart
  - name: start
    service: name=redis state=started
  handlers:
  - name: restart
    service: 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它们地一种机制。
  • 角色一般用于基于主机构建服务的场景中,但是也可以用于构建守护进程等场景中。4

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: cp
  copy: src=nginx-1.18.0-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm
- name: install
  yum: name=/tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm state=latest
- name: conf
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
  tags: nginxconf
  notify: new conf to reload
- name: start service
  service: 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启动时候的pid

events {
    worker_connections  1024; #每个进程允许的最大连接数
}

http { #http请求配置,一个http可以包含多个server

    #定义 Content-Type
    include       /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可以配置多个location
        listen       {{ 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.html
        error_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 reload
  service: name=nginx state=restarted
  • 定义剧本文件(roles.yml
- hosts: web
  remote_user: root
  roles:
    - nginx

最后的目录结构如下:
在这里插入图片描述
执行

ansible-playbook roles.yml

在这里插入图片描述
到这里一个完整版的roles演示示例就完成了,接下来也会真正使用ansible playbook roles应用到真实场景中,请小伙伴耐心等待,小伙伴也可关注我的公众号【大数据与云原生技术分享】,会在公众号里分类整理这些文章,看起来更方便~

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

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

相关文章

LINUX---文件

目录第一部分&#xff1a;文件编程一.打开/创建文件二.文件的写入操作三.文件的读取四.文件的光标应用&#xff1a;计算文件的大小第二部分&#xff1a;文件操作原理&#xff1a;一.文件描述符静态文件和动态文件第三部分&#xff1a;文件编程小应用1.实现CP命令2.修改文件3.写…

安卓玩机搞机技巧综合资源-----修改rom 制作rom 解包rom的一些问题解析【二十一】

接上篇 安卓玩机搞机技巧综合资源------如何提取手机分区 小米机型代码分享等等 【一】 安卓玩机搞机技巧综合资源------开机英文提示解决dm-verity corruption your device is corrupt. 设备内部报错 AB分区等等【二】 安卓玩机搞机技巧综合资源------EROFS分区格式 小米红…

【Vue笔记】Vue组件的创建、使用以及父子组件数据通信常见的几种方式

这篇文章&#xff0c;主要介绍Vue组件的创建、使用以及父子组件数据通信常见的几种方式。 目录 一、Vue组件的使用 1.1、局部组件 1.2、全局组件 1.3、动态组件&#xff08;组件动态切换&#xff09; 1.4、缓存组件 &#xff08;1&#xff09;如何缓存组件 &#xff08;…

微服务技术--Nacos与Eureka

eureka注册中心 远程调用的问题 消费者该如何获取服务提供者具体信息&#xff1f; 服务提供者启动时向eureka注册自己的信息eureka保存这些信息消费者根据服务名称向eureka拉取提供者信息 如果有多个服务提供者&#xff0c;消费者该如何选择&#xff1f; 服务消费者利用负载均…

区块链技术1---密码学基础

摘要&#xff1a;BTC属于加密货币&#xff0c;其中必然涉及到密码学的知识&#xff0c;而比特币比较开放&#xff0c;交易记录&#xff0c;交易金额甚至是底层源代码都是对外开放&#xff0c;那么加密使用在何处&#xff1f;这里就来谈一谈1&#xff1a;哈希哈希函数是密码学的…

client-go实战之六:时隔两年,刷新版本继续实战

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 系列文章链接 client-go实战之一&#xff1a;准备工作client-go实战之二:RESTClientclient-go实战之三&#xff1a;Clientsetclient-go实战之四&#xff1a;…

JavaWeb开发(三)3.3——Spring Bean详解

一、Bean的概念 由 Spring IoC 容器负责创建、管理所有的Java对象&#xff0c;这些管理的对象称为 Bean&#xff0c;Bean 根据 Spring 配置文件中的信息创建。 二、基于XML方式管理bean对象 eg&#xff1a; <?xml version"1.0" encoding"UTF-8"?&…

【B-树、B+树、B* 树】多叉平衡搜索树,解决“IO次数”与“树高”问题~

目录 一、为什么会出现B-树&#xff1f; 面试题&#xff1a; 二、什么是B-树&#xff1f; 2.1、B,B-树,B*树 导航 三、B-树的模拟实现 3.1、插入结点分析 3.1.1、根节点的分裂 3.1.2、继续插入数据&#xff0c;分裂子节点 3.2.3、再次插入数据&#xff0c;导致根节点继…

tomcat和apache有什么区别?如何将内网发布到互联网访问?

tomcat、 apache是比较常用的搭建服务器的中间件&#xff0c;它们之间还是有一些区别差异的&#xff0c;我们通常会根据本地应用场景来选择合适的中间件来搭建服务器。在内网本地部署搭建服务器后&#xff0c;还可以通过快解析端口映射方法&#xff0c;将内网应用地址发布到互联…

Android原生检测Selinux的三种方法

本文介绍 3 种检测 Android 设备 SELinux 状态的方法, Java 层检测Selinux已经没有太多意义,因为不是很靠谱,随便一个hook代码就能绕过,所以我要告诉你如何在 C 层完成检测。这几种方法在效率和抵抗mock SELinux State 的技术方面都不相同,因此在使用之前你需要知道每种方…

Windows server——部署DNS服务

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 本章重点 一.DNS概述 1.DNS的诞生 二.DNS的功能 使用域名访问具有以下优点…

【大厂高频真题100题】《二叉树的序列化与反序列化》 真题练习第23题 持续更新~

二叉树的序列化与反序列化 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。 请设计一个算法来实现二叉树的序列化与反序列化。这里不限…

c语言 图形化贪吃蛇 多种功能 无需安装第三方库 课设 (附代码)

前言 类贪吃蛇是利用c语言模仿并实现经典游戏贪吃蛇&#xff0c;使其在窗口有贪吃蛇活动的规定范围&#xff0c;并完成一系列包括但不限于模仿蛇的移动&#xff0c;方向控制&#xff0c;吃到食物加分&#xff0c;撞上墙壁及蛇头碰到蛇身死亡等游戏功能。 附加功能&#xff1a…

软件测试复习03:动态测试——白盒测试

作者&#xff1a;非妃是公主 专栏&#xff1a;《软件测试》 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录逻辑覆盖法&#xff1a;最常用程序插桩技术基本路径法点覆盖边覆盖边对覆盖主路径覆盖符号测试错误…

前端leaflet框选下载bing遥感图

微软必应bing遥感图。bing地图比百度遥感图清晰很多&#xff0c;19级&#xff0c;百度是18级&#xff0c;同样的18级&#xff0c;bing地图比百度也清晰很多。所以没有必要用百度地图了。不过bing地图仅用于学习&#xff0c;商用要付费。参考了https://xiaozhuanlan.com/topic/6…

CV+Deep Learning——网络架构Pytorch复现系列——Detection(二:RtinaNet)更换backbones

上一话 CVDeep Learning——网络架构Pytorch复现系列——Detection(一&#xff1a;SSD:Single Shot MultiBox Detector 4.推理Detect)https://blog.csdn.net/XiaoyYidiaodiao/article/details/128683973?spm1001.2014.3001.5501 复现Object Detection&#xff0c;会复现的网络…

设计模式-门面模式

医院的例子 现代的软件系统都是比较复杂的&#xff0c;设计师处理复杂系统的一个常见方法便是将其"分而治之"&#xff0c;把一个系统划分为几个较小的子系统。如果把医院作为一个子系统&#xff0c;按照部门职能&#xff0c;这个系统可以划分为挂号、门诊、划价、化…

Web--Jedis

# Redis 1. 概念&#xff1a; redis是一款高性能的NOSQL系列的非关系型数据库 1.1.什么是NOSQL NoSQL(NoSQL Not Only SQL)&#xff0c;意即“不仅仅是SQL”&#xff0c;是一项全新的数据库理念&#xff0c;泛指非关系型的数据库。 随着互联网web2.0网…

Arch Linux 来报道!!!

导读Ubuntu 的制造商 Canonical 早已和微软进行合作&#xff0c;让我们体验了极具争议的 Bash on Windows。外界对此也是褒贬不一&#xff0c;许多 Linux 重度用户则是质疑其是否有用&#xff0c;以及更进一步认为 Bash on Windows 是一个安全隐患。 Unix 的 Bash 是通过 WSL (…

LabVIEW使用VI脚本创建和打开VI

LabVIEW使用VI脚本创建和打开VI按照下列步骤&#xff0c;可以创建一个VI&#xff0c;该VI使用VI脚本创建和打开VI。创建VI前&#xff0c;需先了解VI脚本的基本内容。必须启用VI脚本&#xff0c;才能显示VI脚本选板&#xff0c;使用相关属性和方法。1. 选择文件新建VI&#xff0…