ansible笔记

编程

最近学了ansible视频几节课,全部跟着操作了一遍。操作一遍就能记熟了吗?

不! 不能! 所以,需要将笔记保存下来,以备后查。

###############  Ansible中文权威指南 http://www.ansible.com.cn/ ########

# 一般实验环境

# 192.168.52.6

# 192.168.52.7

# 192.168.52.8

# 192.168.52.9

wget https://mirrors.aliyun.com/epel/7/x86_64/Packages/e/epel-release-7-12.noarch.rpm

rpm -Uvh epel-release-7-12.noarch.rpm

yuminfo ansible

yuminstall -y ansible

rpm -ql ansible |less

file /usr/bin/ansible

# /etc/ansible/ansible.cfg 主配置文件(几乎不必修改)

# /etc/ansible/hosts 主机列表(管理对象)

# /etc/ansible/roles 角色

# hosts文件示例:

[vm]

192.168.52.[7:9]

#cent7[b:d]

[appsvrs]

192.168.52.7

192.168.52.8

[dbsvrs]

192.168.52.9

192.168.52.7

 

上面是基本信息,下面是一些基本命令

# ssh

ansible all -m ping -k # all 则操作hosts中所有主机

# -u 指定用户名,无此参数则默认当前用户

# -k 需要密码认

# 可以使用SSH认证后不必再用 -k

ssh-keygen

ssh-copy-id192.168.52.7

ssh-copy-id192.168.52.8

ssh-copy-id192.168.52.9

ansible all -m ping

ansible-doc -s ping # 获取ping 模块简要帮助

ansible-doc -F |grep zabbix

ansible all --list # 列出所有主机

ansible dbsvrs --list # 列出所有主机

 

常见模块使用

## ping 模块

ansible 192.168.* -m ping # 操作hosts中所有192.168开头主机

ansible appsvrs:dbsvrs -m ping # or

ansible "appsvrs:&dbsvrs" -m ping # and

## command 模块

ansible-doc command

ansible all -a "df -h"

ansible all -a "ls /opt"

ansible all -a "removes=/opt/1.txt cat /opt/1.txt" # 不存在则不执行

ansible dbservers -a "removes=/data/mariadb ls -l /data"

ansible all -a "creates=/opt/1.txt cat /opt/1.txt" # 存在则不执行

ansible dbservers -a "creates=/data/mariadb ls -l /data"

ansible all -a "chdir=/home ls"

## shell 模块

ansible all -m shell -a "echo $HOSTNAME"

# 例:关闭selinux

ansible all -a "ls -l /etc/selinux/"

ansible all -m copy -a "src=/root/config dest=/etc/selinux/config backup=yes" # 本机文件到远程

ansible all -a "cat /etc/selinux/config"

ansible all -m shell -a "rm -f /etc/selinux/config.*" # 删除备份

ansible all -m shell -a "reboot"

ansible all -m shell -a "last reboot"

ansible all -a "getenforce"

ansible all -m shell -a "useradd mongodb"

ansible all -m shell -a "passwd mongodb"

## script 模块

ansible all -m script -a "/root/h.sh"

## copy 复制当前目录某文件到远程

ansible all -m copy -a "src=./h.sh dest=/root/ mode=000 owner=mongodb"

ansible all -a "ls -l /root/"

ansible all -a "cat /root/h.sh"

# 直接向远程目录写文件

ansible all -m copy -a "content="#!/bin/bash

ntpdate cn.pool.ntp.org" dest=/root/f2.sh mode=644 owner=mongodb"

ansible all -a "cat /root/f2.sh"

## fetch 抓取远程文件

ansible all -m shell -a "tar Jcf /tmp/log.tar.xz /var/log/*.log"

ansible all -m fetch -a "src=/tmp/log.tar.xz dest=/opt"

yuminstall -y tree

tree /opt

tar tvf /opt/192.168.52.7/tmp/log.tar.xz

## file 模块

ansible all -m file -a "state=directory mkdir /test" # 创建目录

ansible all -m file -a "name=/test/tmp state=directory"

ansible all -m file -a "name=/tt/tmp/123 state=directory"

ansible all -m file -a "path=/test/f3 state=touch" # 创建空文件

ansible all -m file -a "name=/test/f3 state=absent" # 删除文件

ansible all -m file -a "name=/tt/ state=absent" # 删除目录(包括子目录和文件)

ansible all -m file -a "src=/etc/passwd dest=/test/pwd.lmk state=link" # 创建软链接

ansible all -a "ls -l /test"

## hostname 模块

ansible 192.168.52.7 -m hostname -a "name=cent7b"

## cron 模块

ansible all -m cron -a "minute=* weekday=1,3,5 job="/usr/bin/wall FBI warning" name=warn" # new

ansible all -m cron -a "disabled=true job="/usr/bin/wall FBI warning" name=warn" # disabled

ansible all -m cron -a "disabled=yes job="/usr/bin/wall FBI warning" name=warn" # disabled

ansible all -m cron -a "disabled=Y job="/usr/bin/wall FBI warning" name=warn" # disabled

ansible all -m cron -a "disabled=no job="/usr/bin/wall FBI warning" name=warn" # enabled

ansible all -m cron -a "disabled=false job="/usr/bin/wall FBI warning" name=warn" # enabled

ansible all -m cron -a "state=absent job="/usr/bin/wall FBI warning" name=warn" # delete

## yum 模块

ansible all -m yum -a "name=tree state=latest"

ansible all -m yum -a "name=tree,vim,ntp state=present" # 安装

ansible all -m yum -a "name=tree state=absent" # 删除

ansible all -m shell -a "rpm -q tree"

ansible all -m copy -a "src=/root/samba-4.8.3-6.el7_6.x86_64.rpm dest=/root/" # rpm 安装

ansible all -m yum -a "name=/root/samba-4.8.3-6.el7_6.x86_64.rpm disable_gpg_check=Y"

ansible all -m yum -a "name=lsof update_cache=yes" # 同时更新缓存

ansible all -m yum -a "name=dstat update_cache=yes" # dstat 是监控工具

## service 模块

ansible-doc -s service

ansible all -m service -a "name=zabbix-server state=stopped" # reloaded, restarted, started

ansible all -m service -a "name=mysqld state=restarted"

ansible all -m service -a "name=zabbix-server enabled=no"

ansible all -a "systemctl is-enabled zabbix-server"

## user 模块

ansible appsvrs -m user -a "name=nginx shell=/sbin/nologin system=yes home=/home/nginx groups=root,bin uid=80 comment="nginx service""

ansible all -a "getent passwd nginx"

ansible appsvrs -m user -a "name=nginx state=absent remove=yes"

ansible appsvrs -m group -a "name=nginx system=yes gid=80" # 创建组

ansible appsvrs -m group -a "name=nginx state=absent" # 删除组

ansible all -a "getent group nginx"

 

galaxy 类似于脚本库,可以下载现成的脚本作为参考  控制台则是ansible的交互界面

## ------------------------------- galaxy ------------------------------

ansible-galaxy install geerlingguy.nginx

ansible-galaxy list geerlingguy.nginx

ansible-galaxy list

cd .ansible/roles/

cp geerlingguy.nginx/ my.nginx -rp # 创建副本

ansible-galaxy list

ansible-galaxy remove geerlingguy.nginx/ # 或者直接删除 roles/下的目录

ansible-console # 控制台

# root@appsvrs(2)[f:5] # 用户@组(数量)[请求数:5]

cd 192.168.52.8 # 切换主机

user name=test1 state=absent remove=yes # 删除远程用户

 

YAML 语法 Yet Another Markup Language

#### YAML语法:

# 单一文件中,连续三个字符(---)区分多个档案,而三个点(...)则表示档案结尾

# 次行开始写playbook内容,一般建议写功能

# 使用 # 号注释

# 缩进必须统一,不能空格与Tab混用

# 缩进级别必须一致,程序判定配置的级别是根据缩进和换行来实现

# 严格区分大小写

# k/v 的值可同行也可换行,同行使用冒号分隔(: )

# v 可以是字符串,也可以是另一个列表

# 一个完整的代码块最少需要包括 name 和 task

# 一个 name 只能包括一个 task

# YAML 扩展名为 yml 或 yaml

## List 列表,所有元素以 - 开头

---

# 一个美味水果的列表

- Apple

- Orange

- Strawberry

- Mango

## Dictionary 字典,通常用 k/v 组成

---

# 一位职工的记录

name: Elly

job: Developer

skill: Elite

 

playbook

## ------------------------------- playbook ----------------------------

# hello.yml

---

- hosts: appsvrs

remote_user: root

tasks:

- name: hello

command: hostname

ansible-playbook hello.yml  # 执行 hello.yml

# ansible-vault encrypt hello.yml # 加密文件

# ansible-vault decrypt hello.yml # 解密文件

# ansible-vault view hello.yml # 查看

# ansible-vault edit hello.yml # 编辑

# ansible-vault rekey hello.yml # 换密码

# ansible-vault create h.yml # 直接创建加密的文件

ansible-playbook hello.yml --ask-vault-pass # 直接运行加密文件

 

playbook 操作文件示例

# file.yml

---

- hosts: dbservers

remote_user: root

tasks:

- name: create new file

file: name=/data/newfile state=touch

- name: new user

user: name=test2 system=yes shell=/sbin/nologin

- name: install tree

yum: name=tree

- name: copy config

copy: src=/root/hello.yml dest=/data/

- name: copy test html

copy: src=files/test.html dest=/data/

- name: start service

service: name=squid state=restarted enabled=yes

ansible-playbook --syntax-check file.yml    # not execute

ansible-playbook -C file.yml # check

ansible-playbook file.yml # run

# src文件内容更新后,再次执行playbook,会覆盖旧文件

ansible-playbook file.yml --list-hosts # 列出主机

ansible-playbook file.yml --list-tasks # 列出任务

ansible-playbook file.yml --limit 192.168.52.8 # 限制执行

ansible-playbook file3.yml --ask-vault-pass # 涉及加密文件

# file3.yml

---

- hosts: dbservers

remote_user: root

become: yes # 改变用户

become_user: mongodb # 变成谁

become_method: sudo # playbook 时需要 -K

tasks:

- name: create new file

file: name=/data/newfile5 state=touch

- name: cp files

copy: src=file.yml dest=/data/

- name: cp test html

copy: src=files/test.html dest=/data

ansible-playbook file3.yml -K       # become_user 密码

 

playbook 中使用Handlers 与 notify ,以及 tags

## Handlers  与 notify 

# act1.yml

---

- hosts: vm

remote_user: root

tasks:

- name: install httpd pkg

yum: name=httpd

tags: insthttpd

- name: copy conf file

copy: src=httpd.conf dest=/etc/httpd/conf/ backup=yes

notify:

- restart httpd

- chk httpd process

- name: start service

service: name=httpd state=started enabled=yes

tags: starthttpd

handlers:

- name: restart httpd

service: name=httpd state=restarted

- name: chk httpd process

shell: killall -0 httpd > /tmp/httpd.log # yum install psmisc

# 执行指定的 tags 步骤

ansible-playbook -t insthttpd,starthttpd act1.yml

# tags可以同名,则相同tags的动作都会被执行

ansible-playbook act2.yml -t httpd

 

playbook 中使用变量

#------------------------- 模块 setup 用来收集主机的系统信息

ansible vm -m setup -a "filter=ansible_hostname"

ansible vm -m setup -a "filter=ansible_fqdn"

ansible vm -m setup -a "filter=*ipv4*"

# ------------------------- 变量 ---------------------------------------

# 可以命令行,playbook, role , /etc/ansible/hosts 中定义

## 1. app.yml # 执行时传入变量

---

- hosts: vm

remote_user: root

tasks:

- name: install pkg

yum: name={{ pkname }}

- name: start service

service: name={{ pkname }} state=started enabled=yes

ansible-playbook -e "pkname=vsftpd" app.yml                      # 传入

ansible-playbook -e "pkname1=httpd pkname2=memcached" app2.yml # 多个

# ansible vm -m shell -a "rpm -q httpd memcached "

# ansible vm -m yum -a "name=httpd,memcached state=absent"

## 2. playbook 中定义并使用变量 app3.yml

---

- hosts: vm

remote_user: root

vars:

- pkname1: httpd

- pkname2: vsftpd

tasks:

- name: install pkg

yum: name={{ pkname1 }}

- name: install pkg2

yum: name={{ pkname2 }}

ansible-playbook app3.yml       # 无需再传入变量

## 3. hosts文件中定义变量

[vm]

192.168.52.5 http_port=8181 # 普通变量

192.168.52.6 http_port=8080

192.168.52.7

[vm:vars] # 公共变量

nodename=www

domainame=bbc.com

http_port=80

# app4.yml

---

- hosts: vm

remote_user: root

tasks:

- name: set hostname

hostname: name={{nodename}}{{http_port}}.{{domainame}}

# 变量优先级指定: 命令行 > 配置文件, 普通 > 公共

ansible-playbook -e "nodename=web" app4.yml # 指定变量值

ansible vm -a "hostname"


# 4. 使用系统变量 (如 setup 模块中的) testvars.yml

---

- hosts: vm

remote_user: root

tasks:

- name: create log file

file: name=/data/{{ ansible_fqdn }}.log state=touch mode=600 owner=nginx

ansible-playbook testvars.yml     # ansible_fqdn 为系统变量


# 5. 使用专门的变量文件

# vars.yml

var1: httpd

var2: vsftpd

# testvars2.yml

---

- hosts: vm

remote_user: root

vars_files:

- vars.yml

tasks:

- name: install pkg

yum: name={{ var1 }}

- name: create files

file: name=/data/{{ var2 }}.log state=touch

ansible-playbook testvars2.yml    

ansible vm -m shell -a "rpm -q httpd"

ansible vm -a "ls /data/"

# ansible 管理容量在300台左右,再多,性能跟不上

# gather_facts: false

 

模板的使用

#------------------------- Jinja2 template ----------------------------# 

# template 模块只能用于playbook

ansible-doc template

mkdir template

cp /etc/nginx/nginx.conf template/nginx.conf.j2

ansible vm -m setup |grep cpu # 得到 ansible_processor_vcpus

# 修改模板文件 nginx.conf.j2 修改cpu和端口为变量

user nginx;

worker_processes {{ ansible_processor_vcpus // 2 }};

...

listen {{ http_port }} default_server;

listen [::]:{{http_port }} default_server;

...

# 修改脚本 testemp.yml

---

- hosts: vm

remote_user: root

tasks:

- name: install nginx

yum : name=nginx

- name: copy template

template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

notify: restart nginx

- name: start service

service: name=nginx state=started enabled=yes

handlers:

- name: restart nginx

service: name=nginx state=restarted

ansible-playbook testemp.yml        # 运行并验证

ansible vm -a "netstat -nltp"

ansible vm -m shell -a "ps -aux |grep nginx"

ansible vm -a "cat /etc/nginx/nginx.conf"

 

tasks 中使用 when

# 在 tasks 中使用 when ------------------------------------------------

# 参考 https://www.cnblogs.com/nb-blog/p/10565658.html

ansible vm -m setup -a "filter=ansible_distribution" # CentOS

ansible vm -m setup -a "filter=ansible_distribution_major_version" # 7

# 再次修改 testemp.yml

---

- hosts: vm

remote_user: root

tasks:

- name: install nginx

yum : name=nginx

- name: copy template for centos 7

template: src=nginx.conf7.j2 dest=/etc/nginx/nginx.conf

when:

- ansible_distribution == "CentOS"

- ansible_distribution_major_version == "7"

notify: restart nginx

- name: copy template for centos 6

template: src=nginx.conf6.j2 dest=/etc/nginx/nginx.conf

when: ansible_distribution_major_version == "6"

notify: restart nginx

- name: start service

service: name=nginx state=started enabled=yes

handlers:

- name: restart nginx

service: name=nginx state=restarted

ansible-playbook testemp.yml     # 执行并验证  注意 skipping 信息

ansible vm -a "cat /etc/nginx/nginx.conf"

ansible vm -m shell -a "ps -aux |grep nginx"

 

tasks 中使用 with_items 列表,以及 嵌套子变量

# 迭代 with_items 用法  testitem.yml -----------------------------------

---

- hosts: vm

remote_user: root

tasks:

- name: create some files

file: name=/data/{{ item }} state=touch

with_items:

- f1.txt

- f2.txt

- f3.txt

- name: install some pkg

yum:

name: ["htop", "sl", "hping3"]

# 使用嵌套子变量 testitem2.yml ----------------------------------------

---

- hosts: vm

remote_user: root

tasks:

- name: create groups

group: name={{ item }}

with_items:

- g1

- g2

- g3

- name: create users

user: name={{ item.name }} group={{ item.gp }}

with_items:

- { name: "user1", gp: "g1" }

- { name: "user2", gp: "g2" }

- { name: "user3", gp: "g3" }


ansible-playbook testitem2.yml # 执行并验证

ansible vm -a "cat /etc/group"

ansible vm -a "cat /etc/passwd"

 

使用 for 循环 , if 条件

### for 循环   testfor.yml --------------------------------------------

---

- hosts: vm

remote_user: root

vars:

ports:

- 81

- 82

- 83

tasks:

- name: copy conf

template: src=for1.conf.j2 dest=/data/for1.conf

# templates/for1.conf.j2

{% for p in ports %}

server{

listen {{ p }}

}

{% endfor %}

ansible-playbook testfor.yml         # 执行并验证

ansible vm -a "cat /data/for1.conf"

### for 循环 结合变量字典 testfor2.yml -------------------------------

---

- hosts: vm

remote_user: root

vars:

apps:

- web1:

port: 81

name: app1

dir: /data/web1

- web2:

port: 82

name: app2

dir: /data/web2

- web3:

port: 83

name: app3

dir: /data/web3

tasks:

- name: copy conf

template: src=for2.conf.j2 dest=/data/for2.conf

# templates/for2.conf.j2

{% for p in apps %}

server{

listen {{ p.port }}

servername {{ p.name }}

documentroot {{ p.dir }}

}

{% endfor %}

ansible-playbook testfor2.yml            # 执行并验证

ansible vm -a "cat /data/for2.conf"

## 使用 if 判断 testif.yml --------------------------------------------

---

- hosts: vm

remote_user: root

vars:

apps:

- web1:

port: 81

#name: app1

dir: /data/web1

- web2:

port: 82

name: app2

dir: /data/web2

- web3:

port: 83

#name: app3

dir: /data/web3

tasks:

- name: copy conf

template: src=if.conf.j2 dest=/data/if.conf

# if.conf.j2

{% for p in apps %}

server{

listen {{ p.port }}

{% if p.name is defined %}

servername {{ p.name }}

{% endif %}

documentroot {{ p.dir }}

}

{% endfor %}

ansible-playbook testif.yml            # 执行并验证

ansible vm -a "cat /data/if.conf"

 

### 插播一些 centos 有趣的命令: ---------------------------------------
cal # 当前月 cal -3 三个月
sl # 跑火车 -F -l -a
linux_logo # -L list
echo "dog" |boxes -d dog # yum install boxes
curl http://wttr.in # 天气
#---------------------------------- end --------------------------------

 

roles

### roles  用于层次性,结构化地组织 playbook  --------------------------

# 能够根据层次型结构自动装载变量文件、tasks以及handlers等。

# 在playbook中使用include指令。

# 用于复杂场景,代码复用度高。

# 一般用于基于主机构建服务场景,也可用于构建守护进程场景中。

mkdir roles/{httpd,mysql,memcached,nginx} -pv

# ansible vm -m shell -a "userdel -r nginx"

cd nginx

mkdir tasks templates

# 以nginx 为例,tree 结构如下:

├── nginx_roles.yml

└── roles

├── httpd

├── memcached

├── mysql

└── nginx

├── tasks

│ ├── group.yml

│ ├── main.yml

│ ├── restart.yml

│ ├── start.yml

│ ├── temp.yml

│ ├── user.yml

│ └── yum.yml

└── templates

└── nginx.conf.j2

# group.yml 

- name: create group

group: name=nginx gid=80

# user.yml

- name: create user

user: name=nginx uid=80 group=nginx system=yes shell=/sbin/nologin

# yum.yml

- name: install nginx

yum: name=ngin

# temp.yml

- name: copy conf

template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

# start.yml

- name: start nginx

service: name=nginx state=started enabled=yes

# main.yml

- include: group.yml

- include: user.yml

- include: yum.yml

- include: temp.yml

- include: start.yml

# nginx_roles.yml

---

- hosts: vm

remote_user: root

roles:

- role: nginx

ansible-playbook nginx_roles.yml   # 执行并验证

ansible vm -a "cat /etc/nginx/nginx.conf"

ansible vm -a "ps -aux |grep nginx"

# 以apache为例 --------------------------------------------------

ansible vm -m shell -a "yum remove -y httpd"

ansible vm -m user -a "name=apache state=absent remove=yes"

# tree

├── httpd_role.yml

└── roles

└── httpd

├── files

│ └── httpd.conf

├── tasks

│ ├── cpfile.yml

│ ├── main.yml

│ ├── yum.yml

│ ├── start.yml

│ └── user.yml

└── templates

# main.yml

- include: user.yml

- include: yum.yml

- include: cpfile.yml

- include: start.yml

# httpd_role.yml

---

- hosts: vm

remote_user: root

roles:

- httpd

ansible-playbook httpd_role.yml   # 执行并验证

 

调用 多个 role 或跨项目调用 role

# some_roles.yml  调用多个 role   ----------------------------------

---

- hosts: vm

remote_user: root

roles:

- httpd

- nginx

# main.yml 跨项目调用别的role中任务

- include: roles/nginx/tasks/temp.yml

# temp.yml # 注意文件内容中使用绝对路径

- name: copy conf

template: src=/root/roles/nginx/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf

# tags when ---------------------------------------------

---

- hosts: vm

remote_user: root

roles:

- { role: httpd, tags: ["web","httpd"] }

- { role: nginx, tags: ["web","nginx"], when: ansible_distribution_major_version == "7" }

- { role: app, tags: "app" }

ansible-playbook -t web some_roles.yml

 

来一个综合练习 

### 综合练习 app -------------------------------------------------------

cd /root/roles/app

mkdir tasks templates vars handlers files

# group.yml

- name: create group

group: name=app system=yes gid=123

# user.yml

- name: crt user

user: name=app system=yes shell=/sbin/nologin uid=123

# yum.yml

- name: install pkg

yum: name=httpd

# template httpd.conf.j2 包含:

Listen {{ ansible_processor_vcpus * 10 }}

User {{ username }}

Group {{ groupname }}

# vars/main.yml

username: app

groupname: app

# copy.yml

- name: copy conf

copy: src=vhost.conf dest=/etc/httpd/conf.d/

# tmpl.yml

- name: copy conf

template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf

notify: restart httpd

# start.yml

- name: start httpd

service: name=httpd state=started enabled=yes

# handlers/main.yml

- name: restart httpd

service: name=httpd state=restarted

# httpd_role.yml

---

- hosts: vm

remote_user: root

roles:

- app

# tree

├── httpd_role.yml

├── roles

│ ├── app

│ │ ├── files

│ │ │ └── vhost.conf

│ │ ├── handlers

│ │ │ └── main.yml

│ │ ├── tasks

│ │ │ ├── copy.yml

│ │ │ ├── group.yml

│ │ │ ├── main.yml

│ │ │ ├── start.yml

│ │ │ ├── tmpl.yml

│ │ │ ├── user.yml

│ │ │ └── yum.yml

├── templates

│ └── httpd.conf.j2

└── vars

└── main.yml

# 执行并验证:

ansible-playbook httpd_role.yml

ansible vm -m shell -a "head /etc/httpd/conf/httpd.conf"

ansible vm -m shell -a "netstat -nltp"

ansible vm -m shell -a "ps -aux |grep httpd"

 

练习 :memcached

# memcached 安装: 根据内存大小更改配置文件 ----------------------------

# templates/memcached.j2

PORT="11211"

USER="memcached"

MAXCONN="1024"

CACHESIZE="{{ ansible_memtotal_mb // 4 }}"

OPTIONS=""

# tasks/yum.yml

- name: install memcached

yum: name=memcached

# start.yml

- name: start memcached

service: name=memcached state=started enabled=yes

# tmpl.yml

- name: copy conf

template: src=memcached.j2 dest=/etc/sysconfig/memcached

# main.yml

- include: yum.yml

- include: tmpl.yml

- include: start.yml

# memcached_role.yml

---

- hosts: vm

remote_user: root

roles:

- memcached

# 执行并验证:

ansible-playbook memcached_role.yml

ansible vm -m shell -a "cat /etc/sysconfig/memcached"

 

以上是 ansible笔记 的全部内容, 来源链接: utcz.com/z/514228.html

回到顶部