23_linux笔记-ansible


博客cPen_web

示例1:永久修改selinux

[root@cPen_A ~]# vim /etc/selinux/config 
SELINUX=disabled

示例2:看当前系统有多少连接 (establish)

[root@cPen_B ~]# netstat -anplut|grep -E "ESTABLISHED|LISTEN|TIME_WAIT"|awk -F" " {'print $6'}|sort|uniq -c
      2 ESTABLISHED
      2 LISTEN
#-------------------------------------------------------------------------------
[root@cPen_B ~]# netstat -anplut
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:2233            0.0.0.0:*               LISTEN      911/sshd            
tcp        0    232 192.168.0.31:2233       192.168.0.42:54290      ESTABLISHED 1402/sshd: root [pr 
#-------------------------------------------------------------------------------------------------------------
# pstree	查看进程之间的关系
# netstat	查看当前网络连接

知识点1 SSH访问控制

SSH使用TCP Wrappers实现访问控制 # 注:做访问控制
主要配置文件
·/etc/hosts.allow
·/etc/hosts.deny

示例:/etc/hosts.deny

[root@cPen_A ~]# vim /etc/hosts.deny 
sshd:192.168.0.31	
# 注:访问控制,拒绝192.168.0.31 不需要重启服务,有守护进程帮它控制
#注:主机公钥在 /etc/ssh/下面	默认使用ecdsa模式
#注:known_hosts文件里有什么	前面是ip地址,后面是公钥
#注:authorized_keys	放受信任的公钥

知识点2 ssh隧道

#注:本地端口转发
CSDN https://www.cnblogs.com/keerya/p/7612715.html
端口转发:A、C、B主机。主机B起了个nginx服务 端口号80;主机A不能直接访问主机B,但主机A可以访问主机C,主机C可以访问主机B (A–>C–>B);A可以ssh到C,A跳到C,然后访问B的80端口 (nginx)。现在 在主机C上面建立一个隧道,隧道开启15577端口连接B的80端口,A去访问15577端口相当于去访问B的80映射

#注:ssh隧道 第一个用于不能直接访问的情况;第二个考虑密文传输
[root@cPen_C ~]# lsof -i:15577			# 注:在C主机上操作,15577端口未被占用
[root@cPen_C ~]# ssh -g -L 15577:192.168.0.39:80 sanchuang@192.168.0.39 -p 2233
#注:192.168.0.39 右边B主机ip地址		# 注:在C主机上开通一个隧道 端口为15577
[root@cPen_A ~]# curl 192.168.0.48:15577	# 注:模仿网络访问 (80端口nginx网页使用curl访问)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">	# 注:返回的内容
#注:192.168.0.48 中间C主机ip地址		# 注:注意防火墙	iptables -F
#注:访问中间C主机的15577端口 转接成右边B主机的80端口
#注:注意 不能绑定到本地的回环地址 127.0.0.1	只能访问自己 (所以 -g) -g作用 本地所有ip都是访问
#注:- L是本地端口转发
#注:一般可以开启65535个端口

#总结:ssh隧道
端口转发
1、关闭防火墙
2、关闭selinux

#本地端口转发
# ssh -g -L 15577:192.168.0.39:80 192.168.0.39 -p 2233	# 注:C主机上执行 把B主机80端口映射本地15577端口

实验环境:
A主机:192.168.0.132
C主机:192.168.0.48
B主机:192.168.0.39
在C主机上执行:[root@cPen_C ~]# ssh -g -L 15577:192.168.0.39:80 192.168.0.39 -p 2233
把B主机的80端口映射到本地的15577端口
访问C主机的15577端口就是访问B主机的80端口

#远程端口转发
# ssh -R 15566:192.168.0.39:80 -fN 192.168.0.132 -p 2233 # 注:C主机上 把B主机80端口 映射到 A主机15566端口

远程端口转发:在C主机上执行:[root@C .ssh]# ssh -R 15566:192.168.0.39:80 -fN 192.168.0.132 -p 2233
把B主机的80端口映射到A主机的15566端口
访问A主机的15566就是访问B主机的80

#注:A主机 192.168.0.132
#注:B主机 192.168.0.39
#注:在C主机上建立远程通道,在C主机上为A主机启动15566端口,映射到B主机
[root@cPen_A ~]# lsof -i:15566				# 注:A主机开启15566端口
sshd    2067 root    8u  IPv6  38604      0t0  TCP localhost:15566 (LISTEN)	# 注:监听的是本地回环地址
sshd    2067 root    9u  IPv4  38605      0t0  TCP localhost:15566 (LISTEN)
[root@cPen_A ~]# curl 127.0.0.1:15566			# 注:访问本地15566端口映射到B主机的80端口
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> # 返回的内容

知识点3 ansible服务

ansible是一个自动化运维工具的名称
基于Python开发,集合了众多运维工具的优点(puppet,fabric,slatstack),实现批量系统配置,程序的部署,批量运行命令等

Linux运维:自动化(脚本),智能化,平台化

Linux运维人员,人肉运维不可取
诞生了一系列的运维工具,ansible就是其中之一

日常运维:
1、软件安装
2、服务的配置
3、运行脚本
4、升级
5、备份

ansible基于Python开发,依赖于:paramiko,PyYaml和jinja三个关键组件
#其他服务需要部署agent,而ansible只需要部署到server,只要十万台的key都上传到其他机器上
#注:glibc 内核底层的库

#实验环境
a: 192.168.0.132(ansible)
c: 192.168.0.48
b: 192.168.0.39
实验前提,做好免密码认证,详见ssh服务
a --> b , a --> c a可以免密码登录到b和c

1、在a上安装ansible
[root@cPen_A .ssh]# yum install epel-release # 注:安装epel源
[root@cPen_A .ssh]# yum install ansible # 注:安装ansible
2、配置
配置目录:
/etc/ansible/ansible.cfg
/etc/ansible/hosts
这个配置文件就是默认的主机清单配置文件,可以通过重新定义
备份/etc/ansible/hosts文件
编辑/etc/ansible/hosts文件

#将需要管理的主机添加到webser组
#如果通过ssh登录的端口不是22号端口,就需要在配置文件中指明端口号……没写完
[root@cPen_A ansible]# cp hosts{,.bak}	# 注:备份
[root@cPen_A ansible]# ls
ansible.cfg  hosts  hosts.bak  roles
[root@cPen_A ansible]# >hosts			# 注:老的清空
[root@cPen_A ansible]# vim hosts			
[webser]
192.168.0.31:2233
192.168.0.55
[root@cPen_A /]# cd /etc
[root@cPen_A etc]# ls |grep ansible
ansible
[root@cPen_A etc]# cd ansible
[root@cPen_A ansible]# ls
ansible.cfg  hosts  roles						# 注:host定义主机清单
[root@cPen_A ansible]# less ansible.cfg 
#inventory      = /etc/ansible/hosts				# 注:主机清单
#library        = /usr/share/my_modules/
#module_utils   = /usr/share/my_module_utils/
#remote_tmp     = ~/.ansible/tmp
……
[root@cPen_A ansible]# less hosts 
## [webservers]						# 注:[中括号]里webservers 组名  对这个组进行访问控制
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110

3、ansible使用
-m 指定模块名

HOST-PATTERN #匹配主机模式,如all表示所有主机
-m MOD_NAME #模块名 如:ping
-a MOD_ARGS #模块执行的参数
-f FORKS #生成几个子进行程执行
-C #(不执行,模拟跑)
-u Username #某主机的用户名
-c CONNection #连接方式(default smart)

ansible 主执行程序,一般用于命令行下执行
ansible-playbook 执行playbook中的任务
ansible-doc 获取各模块的帮助信息

[root@cPen_A ~]# ansible -h					# 注:ansible -h帮助文档
[root@cPen_A ~]# ansible
………………
ansible: error: too few arguments
[root@cPen_A ~]# which ansible
/usr/bin/ansible
[root@cPen_A ~]# ls -al /bin/ansible
lrwxrwxrwx 1 root root 20 11月 24 16:41 /bin/ansible -> /usr/bin/ansible-2.7
Ansible
[root@cPen_A ~]# ansible all -m shell -a "ip a"	# 注:匹配所有主机 使用shell模块 执行ip a
[root@cPen_A ~]# ansible all -m shell -a "mkdir /tmp/sc"
……
192.168.0.55 | CHANGED | rc=0 >>				# 注:返回0 执行执行成功
……
[root@cPen_A ~]# ansible webser -m shell -a "mkdir /tmp/sc"	# 注:匹配webser组	没写完
192.168.0.55 | FAILED | rc=1 >>				# 注:返回1 表示执行失败

知识点4 了解云计算

云计算
openstack
docker
kvm
虚拟化技术:在本身物理机的基础上虚拟出云主机
#唯一的不好是 安全性不高 数据保存在别人那里的 (影响不大)

#trouble shooting的能力 问题解答的能力

#注:ssh开启2种验证 - 先公钥认证 再密码认证 密码认证失败 提示permit deny

知识点5 ansible不是守护进程

#ansible 不是守护进程 执行ansible命令的时候才会执行ansible
#守护进程:一直在内存里面,等待别人连接
#ssh是守护进程
#执行1条命令 命令不是守护进程

#ansible不是一个守护进程(守护进程:起来后一直在内存中运行,等待其他人访问)
#ansible就是一个命令脚本,使用Python写的

#[root@cPen_A ansible]# sudo -i			#注:直接回到root用户

知识点6 ansible的模块

ansible的模块

1、copy模块

从本地copy文件分发到目录主机路径 
	参数说明:
	src= 源文件路径			# 注:source 源
dest= 目标路径 			# 注:destination 目的地
注意src= 路径后面带/ 表示带里面的所有内容复制到目标目录下,不带/是目录递归复制过去
	content= 自行填充的文件内容
	owner 属主
	group 属组
	mode权限

示例1:shell模块、copy模块

#示例1:使用ansible 在B、C主机创建/lianxi 目录
#-m	指定模块
#-a	传的参数
ansible 接 指定主机 -m 指定模块 -a 执行的参数
[root@cPen_A ansible]# ansible all -m shell -a "mkdir /lianxi -p"
#注:rc ==> reutrn code --> 为0表示执行成功
#注:rc ==> reutrn code --> 为1表示执行失败
#示例2:将ansible-copy文件 复制到主机B、C/lianxi/ansible目录下,指定权限属主数组
[root@cPen_A lianxi]# vim ansible-copy
[root@cPen_A lianxi]# ansible all -m copy -a "src=/lianxi/ansible-copy dest=/lianxi/ansible mode=777 owner=sanchuang group=sanchuang"
#注:确认B、C主机 指定的用户sanchuang和组sanchuang存在
#md5sum	一般来说 是 信息的摘要		判定文件是否被修改

示例2:指定webser组,将/etc/passwd 赋值到主机/tmp目录下,指定权限777

[root@cPen_A lianxi]# ansible webser -m copy -a "src=/etc/passwd dest=/tmp mode=777"

示例3:copy src路径后面带/不带/的区别

#注:src= 路径后面带/ 表示带里面的所有内容复制到目标目录下,不带/是目录递归复制过去
#注:不带/
[root@cPen_A copy_dir]# ansible all -m copy -a "src=/lianxi/copy_dir dest=/lianxi/ansible"
#注:带/
[root@cPen_A copy_dir]# ansible all -m copy -a "src=/lianxi/copy_dir/ dest=/lianxi/ansible"

#带/表示拷贝目录下的子文件或者子文件夹
#不带/表示拷贝整个目录

2、fetch模块

#注:从远程主机拉取文件到本地

示例

[root@cPen_A lianxi]# ansible webser -m fetch -a "src=/etc/hostname dest=/lianxi mode=644"
192.168.0.22 | CHANGED => {
    "changed": true, 
    "checksum": "c468f7340237d9f531122f5b03345ce8ac5641b4", 		  # 注:拉去下来后会比较
    "dest": "/lianxi/192.168.0.22/etc/hostname", 
    "md5sum": "8d23b0947f191eb9c20728677271eb4d", 
    "remote_checksum": "c468f7340237d9f531122f5b03345ce8ac5641b4", # 注:和远程比较 内容是否变更
    "remote_md5sum": null
}
#注:大文件传送中途 突然断掉了 ,文件没有传完  保存的md5sum和它的md5sum不一样
#注:如果2个值一致	说明传完了
[root@cPen_A lianxi]# ls				# 注:路径自动加了个以ip地址为名的文件夹
192.168.0.20  192.168.0.22  ansible-copy  copy_dir
[root@cPen_A lianxi]# cd 192.168.0.20
[root@cPen_A 192.168.0.20]# ls
etc
从远程主机拉取文件到本地
fetch会自动的在dest指定目录后加上远程主机命名的目录结构后面接src目录结构
fetch存储到本地的目录结构	dest + 远程主机名 + src

#注:md5可以判定	1、文件是否修改;2、文件是否传完
#注:或者使用任何hash算法中的其中一种,去比较值是否相等

3、command模块

在远程主机上执行命令,属于裸执行,非键值对显示;不进行shell解析

示例1:command、shell

[root@cPen_A 192.168.0.20]# ansible all -m command -a "ifconfig"
[root@cPen_A 192.168.0.20]# ansible all -m shell -a "ifconfig"

示例2:command裸执行 (后面传的参数不会做解析)

#注:把ifconfig|grep inet整个当做1个命令去执行
[root@cPen_A 192.168.0.20]# ansible all -m command -a "ifconfig|grep inet"
192.168.0.22 | FAILED | rc=2 >>
[Errno 2] 没有那个文件或目录
#属于裸执行,不会解析它的管道符号 会认为ifconfig|grep inet 是一个命令

#注:shell可以 (后面传的参数会做解析)
[root@cPen_A 192.168.0.20]# ansible all -m shell -a "ifconfig|grep inet"
[root@cPen_A ansible]# ifconfig			# 注:查看网卡(看的东西多一点)
#注:可以看接收包、返回包、字节,有多少错误
[root@cPen_A ansible]# ip a				# 注:查看网卡

4、shell模块

示例

[root@cPen_A 192.168.0.20]# ansible all -m shell -a "ifconfig|grep inet"
跟command一样,只不过shell模块可以解析管道之类的功能

5、file模块

设置文件属性(创建文件)
	常用参数:
	path目标路径
	state directory为目录,link为软件链接
	group 目录属组
	owner 属主
	等,其他参数通过ansible-doc -s file 获取

state --
absent	删除文件和目录的
directory	目录
touch	新建空文件
link		软链接
hard		硬链接

示例1:查看file文件帮助信息

[root@cPen_A lianxi]# ansible-doc -s file			# 注:查看file文件帮助信息

示例2:在目标主机/tmp目录下创建目录
#注:创建文件目录

[root@cPen_A lianxi]# ansible all -m file -a "path=/tmp/sanchuang state=directory"

示例3:设置修改文件属性

[root@cPen_A lianxi]# ansible all -m file -a "path=/tmp/passwd owner=sanchuang"

6、cron模块

6、通过cron模块对目标主机生成计划任务
常用参数:
除了分(minute)(hour)(day)(month)(week)外
name: 本次计划任务的名称
state: present 生成(默认) |absent 删除 (基于name)
#注:首先查看程序有没有起来
[root@cPen_A ~]# ps -ef |grep crond
root        702      1  0 10:59 ?        00:00:00 /usr/sbin/crond -n
root       3582   3553  0 14:41 pts/3    00:00:00 grep --color=auto crond
#注:学会看日志
[root@cPen_A ~]# cd /var/log/
[root@cPen_A log]# less cron
Nov 25 12:01:01 cPen_A run-parts(/etc/cron.hourly)[3498]: finished 0anacron

示例1:添加计划任务

#注:每三分钟输出当前时间,到/tmp/time.txt文件中
[root@cPen_A log]# ansible all -m cron -a "minute=*/3 job='date >>/tmp/time.txt' name=date_test state=present"		# 注:minute=*/3	指定每3分钟 date >>/tmp/time.txt 命令
[root@cPen_B ~]# crontab -l
#Ansible: date_test
*/3 * * * * date >>/tmp/time.txt

[root@cPen_A log]# ansible 192.168.0.20 -m cron -a "minute=*/3 job='date >>/tmp/time.txt' name=date_test state=present"		# 注:可以单独为某个主机设置  并非一定批量处理

示例2:删除计划任务

[root@cPen_A log]# ansible 192.168.0.20 -m cron -a  "name=date_test state=absent"

ntp服务是一个时间管理服务器
示例:ntp服务 系统时间管理服务

[root@cPen_A log]# yum install ntp				# 注:centos7
[root@cPen_B ~]# yum install chrony				# 注:centos8里面  ntp已被 chrony取代
[root@cPen_A log]# ntpdate ntp1.aliyun.com		# 注:同步阿里云的时间
#注:使用ntp客户端 同步ntp的服务器 把时间同步

7、yum模块

7、故名思义就是yum安装软件包的模块;
常用参数说明:
enablerepo,disablerepo表示启用与禁用某repo库
name 安装包名
state (present' orinstalled', latest')表示安装, (absent' or `removed') 表示删除

#注:name安装的包名	state 安装还是卸载

示例:安装wget

[root@cPen_A log]# ansible all -m yum -a "name=wget state=installed"

示例:卸载wget

[root@cPen_A log]# ansible all -m yum -a "name=wget state=absent"

8、service模块

8、服务管理模块
常用参数:
name:服务名
state:服务状态  started(启动)	stopped(关闭)	restarted(重启)	reloaded(重新加载)
enabled: 是否开机启动 true|false
runlevel: 启动级别 (systemed方式忽略)
#安装文件传输服务vsftpd
[root@cPen_A log]# ansible all -m yum -a "name=vsftpd state=installed"

示例:关闭vsftpd服务

[root@cPen_A log]# ansible all -m service -a "name=vsftpd state=stopped"

示例:开启vsftpd服务

[root@cPen_A log]# ansible all -m service -a "name=vsftpd state=started"

9、script模块

把本地的脚本传到远端执行;前提是到远端可以执行,不要把Linux下的脚本同步到windows下执行;

#注:只在远程服务器执行脚本,不上传脚本到远程服务器

[root@cPen_A ~]# vim test.sh
#!/bin/bash
echo "test ansible" >>/tmp/ansible.txt
[root@cPen_A ~]# ansible all -m script -a "/root/test.sh"	# 注:/root/test.sh脚本路径

示例:执行慢 机器多 怎么解决
答:可以使用多进程去执行
-f 6 指定6个进程去执行

知识点7 查看系统版本

[root@cPen_B ~]# uname -r					# 注:查看系统内核
4.18.0-193.el8.x86_64
[root@cPen_B ~]# cat /etc/redhat-release 		# 注:查看/etc/redhat-release 去查看系统版本
CentOS Linux release 8.2.2004 (Core) 

知识点8 链接

示例1:软链接

[root@cPen_A lianxi]# ln -s ansible-copy ansible-copy-likcs-s	#注:前面原文件 后面链接文件
[root@cPen_A lianxi]# ls -al 		# 注:-s soft软
lrwxrwxrwx   1 root root  12 11月 25 11:30 ansible-copy-likcs-s -> ansible-copy
#注:软连接	相当于快捷方式
#注:软链接删掉不会影响原文件,软链接的原文件删掉了会影响链接文件

示例2:硬链接

[root@cPen_A lianxi]# ln ansible-copy ansible-copy-link
[root@cPen_A lianxi]# ls -al
-rw-r--r--   2 root root  20 11月 25 10:12 ansible-copy-link
rm -rf 删除源文件 硬链接文件 依旧没事
#注:硬链接 可以去做备份
#注:硬链接的原文件删掉了不会影响链接文件
#软链接、硬链接
#创建一个硬链接 文件的链接数会+1
#删除硬链接文件或者是源文件  只是把文件的链接数-1  文件不会被真正删除
#创建一个硬链接
[root@cPen_A lianxi]# ls -al
-rw-r--r--   2 root root  20 11月 25 10:12 ansible-copy		# 注:链接为2
#注:软链接
lrwxrwxrwx   1 root root  12 11月 25 11:30 ansible-copy-likcs-s -> ansible-copy # 注:链接为1
#注:硬链接
-rw-r--r--   2 root root  20 11月 25 10:12 ansible-copy-link	# 注:链接为2
符号链接数 1 是
rm -rf 删除的是 文件名 和 磁盘里面data的链接
data还存在于磁盘里 ,过一段时间 新的数据会覆盖 data
#注:为1表示删除了后就没有了,为2表示删除后还有

知识点9 playbook

如果ansible的各模块(能实现各种功能)是车间里的各工具;playbook就是指导手册,目标远程主机就是库存和原料对象
#注:语法 yaml格式配置
1、playbook的核心元素
hosts : playbook配置文件作用的主机
tasks: 任务列表
variables: 变量 
templates:包含模板语法的文本文件
handlers :由特定条件触发的任务
roles :用于层次性、结构化地组织playbook。roles 能够根据层次型结构自动装载变量文件、tasks以及handlers等
2、playbook运行方式
ansible-playbook --check 只检测可能会发生的改变,但不真执行操作
ansible-playbook --list-hosts 列出运行任务的主机
ansible-playbook --syntax-check playbook.yaml 语法检测
ansible-playbook -t TAGS_NAME playbook.yaml 只执行TAGS_NAME任务
ansible-playbook playbook.yaml 运行

示例1:编写/执行 playbook

#注:把A机器的/etc/passwd复制到其他机器的/tmp/passwd_tmp下
[root@cPen_A ~]# vim ansible_playbook_sc.yaml		#注:编写playbook
- hosts: all
  remote_user: root
  tasks:
  - name: up file
    copy: src=/etc/passwd dest=/tmp/passwd_tmp
#执行playbook
[root@cPen_A ~]# ansible-playbook ansible_playbook_sc.yaml 

示例2:yaml文件怎么去编写

#第1步 先安装python3:yum install python3
#第2步 使用pip3安装PyYaml模块
[root@cPen_A ~]# pip3 install PyYaml
[root@cPen_A ~]# python3
>>> import yaml
>>> fp = open("ansible_playbook_sc.yaml")
>>> dict = yaml.load(fp)
>>> dict
[{'hosts': 'all', 'remote_user': 'root', 'tasks': [{'name': 'up file', 'copy': 'src=/etc/passwd dest=/tmp/passwd_tmp'}]}]
#注:使用
1、创建yaml文件
[root@cPen_A ~]# cat ansible_playbook_sc.yaml 	# 注:类似于字典形式 - 相当于list ;里面相当于字典
- hosts: all								# 注:对所有主机生效(什么组)
  remote_user: root						# 注:root用户执行
  tasks:									# 注:让它做什么事情
  - name: up file							# 注:事情名字叫up file
    copy: src=/etc/passwd dest=/tmp/passwd_tmp	# 注:使用copy模块 执行源 目的地址
2、可以使用Python解析yaml
>>> import yaml
>>> fp = open("ansible_playbook_sc.yaml")
>>> dict = yaml.load(fp)
>>> dict
[{'hosts': 'all', 'remote_user': 'root', 'tasks': [{'name': 'up file', 'copy': 'src=/etc/passwd dest=/tmp/passwd_tmp'}]}]
#注:使用copy模块 来指定src dest

示例3:多个操作

[root@cPen_A ~]# vim ansible_playbook_sc.yaml					# 注:编写
- hosts: all
  remote_user: root
  tasks:
  - name: up file
    copy: src=/etc/passwd dest=/tmp/passwd_tmp
  - name: download redis
    yum: name=redis state=installed
- hosts: webser
  tasks:
  - name: remove file
    shell: rm -rf /tmp/passwd_tmp
[root@cPen_A ~]# ansible-playbook ansible_playbook_sc.yaml 		# 注:运行
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mycpen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值