浅谈ANSIBLE模块

ansible介绍

  • ansible:自动化运维工具,实现了批量系统配置、批量程序部署、批量运行命令
  • 特性:
    模块化:调用特定的模块,完成特定任务
    基于Python语言实现:包含Paramiko, PyYAML和Jinja2三个关键模块
    部署简单:agentless,不需在被配置主机安装客户端
    支持自定义模块
    支持playbook
    幂等性:任意多次执行所产生的影响均与一次执行的影响相同
  • ansible架构图
    在这里插入图片描述

ansible 相关文件

在这里插入图片描述

  • 文件结构
    配置文件:/etc/ansible/ansible.cfg
    主机清单:/etc/ansible/hosts
    存放角色的目录:/etc/ansible/roles/
  • Ansible 的配置文件 /etc/ansible/ansible.cfg,其中大部分的配置内容无需进行修改
[defaults]
#inventory = /etc/ansible/hosts # 主机列表配置文件
#library = /usr/share/my_modules/ # 库文件存放目录
#remote_tmp = $HOME/.ansible/tmp #临时py命令文件存放在远程主机目录
#local_tmp = $HOME/.ansible/tmp # 本机的临时命令执行目录
#forks = 5 # 默认并发数
#sudo_user = root # 默认sudo 用户
#ask_sudo_pass = True #每次执行ansible命令是否询问ssh密码
#ask_pass = True
#remote_port = 22
#host_key_checking = False # 检查对应服务器的host_key,建议取消注释
#log_path=/var/log/ansible.log #日志文件,建议启用
#module_name = command #默认模块,可以修改为shell模块
  • 主机清单配置文件格式:
[mysqlsrv]     // 主机组名,包含下面的主机
172.20.54.1
172.20.54.2

[websrv]
172.20.54.3
172.20.54.4
  • ansible相关工具
    /usr/bin/ansible 主程序,临时命令执行工具
    /usr/bin/ansible-doc 查看配置文档,模块功能查看工具
    /usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
    /usr/bin/ansible-playbook 定制自动化任务,编排剧本工具
    /usr/bin/ansible-pull 远程执行命令的工具
    /usr/bin/ansible-vault 文件加密工具
    /usr/bin/ansible-console 基于Console界面与用户交互的执行工具
    利用ansible实现管理的主要方式:
    • Ad-Hoc 即利用ansible命令,主要用于临时命令使用场景
    • Ansible-playbook 主要用于长期规划好的,大型项目的场景,需要有前期的规划过程

ansible工具

1️⃣ansible-doc 此工具用来显示模块帮助

  • 格式
ansible-doc [options] [module...]
-l, --list #列出可用模块
-s, --snippet #显示指定模块的playbook片段
  • 范例:
#列出所有模块
ansible-doc -l
#查看指定模块帮助用法
ansible-doc ping
#查看指定模块帮助用法
ansible-doc -s ping

2️⃣ansible
此工具通过ssh协议,实现对远程主机的配置管理、应用部署、任务执行等功能

  • 建议:使用此工具前,先配置ansible主控端能基于密钥认证的方式联系各个被管理节点
  • 范例:利用sshpass批量实现基于key验证
ssh-keygen -f /root/.ssh/id_rsa -P ''   / 生成密钥对
NET=192.168.100
export SSHPASS=password                 / 定义密码
for IP in {1..200};do
sshpass -e ssh-copy-id $NET.$IP         / 托管密码for循环
done
  • 语法格式 ansible <host-pattern> [-m module_name] [-a args]
  • 选项说明
--version #显示版本
-m module #指定模块,默认为command
-v #详细过程 –vv -vvv更详细
--list-hosts #显示主机列表,可简写 --list
-k, --ask-pass #提示输入ssh连接密码,默认Key验证
-C, --check #检查,并不执行
-T, --timeout=TIMEOUT #执行命令的超时时间,默认10s
-u, --user=REMOTE_USER #执行远程执行的用户
-b, --become #代替旧版的sudo 切换
--become-user=USERNAME #指定sudo的runas用户,默认为root
-K, --ask-become-pass #提示输入sudo时的口令
  • ansible命令执行过程

    1. 加载自己的配置文件 默认/etc/ansible/ansible.cfg
    2. 加载自己对应的模块文件,如:command
    3. 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
    4. 给文件+x执行
    5. 执行并返回结果
    6. 删除临时py文件,退出
  • ansible 的执行状态:

    • 绿色:执行成功并且不需要做改变的操作
    • 黄色:执行成功并且对目标主机做变更
    • 红色:执行失败

3️⃣ansible-galaxy
此工具会连接 https://galaxy.ansible.com 下载相应的roles
范例:

#列出所有已安装的galaxy
ansible-galaxy list
#安装galaxy
ansible-galaxy install geerlingguy.redis
#删除galaxy
ansible-galaxy remove geerlingguy.redis

ansible常用模块

command模块

  • 功能:命令模块,默认模块,用于在远程主机执行命令,
  • 缺点:运行的命令中无法使用变量,管道。如果需要使用管道、变量,请使用raw模块,或者shell模块。
[root@node1 ~]# ansible-doc -s command
- name: 在远程节点执行命令
action: command
chdir           # 在执行命令之前,先切换到该目录
creates         # 一个文件名,当这个文件存在,则该命令不执行,可以用来做判断
executable      # 切换shell来执行命令,需要使用命令的绝对路径
free_form=      #要执行的Linux指令,一般使用Ansible的-a参数代替。
removes         #一个文件名,这个文件不存在,则该命令不执行,与creates相反的判断

shell模块

  • 功能:与command模块相似,执行的命令中有管道或者变量,就需要使用shell
[root@node1 ~]# ansible-doc -s shell
- name: Execute commands in nodes.
action: shell
chdir       # 执行之前,先cd到指定目录在执行命令
creates     # 一个文件名,当这个文件存在,则该命令不执行
executable  # 切换shell来执行命令,需要使用命令的绝对路径
free_form=  # 执行的命令
removes     # 一个文件名,这个文件不存在,则该命令不执行
  • 注意:调用bash执行命令 类似 cat /tmp/test.md | awk -F‘|’ ‘{print $1,$2}’ &> /tmp/example.txt 这些复杂命令,即使使用shell也可能会失败,解决办法:写到脚本时,copy到远程,执行,再把需要的结果拉回执行命令的机器

script模块

  • 功能:在远程主机上运行ansible服务器上的脚本
[root@node1 ~]# ansible-doc -s script
- name: 将本地脚本复制到远程主机并运行之
action: script
creates      # 一个文件名,当这个文件存在,则该命令不执行
free_form=   # 本地脚本路径
removes      # 一个文件名,这个文件不存在,则该命令不执行
  • 语法格式
    ansible webserver -m script -a '/root/script.sh'

copy模块

  • 功能:从ansible服务器主控端复制文件到远程主机
[root@node1 ~]# ansible-doc -s copy
- name: 将文件复制到被管理主机
action: copy
backup          # 创建一个备份文件包括时间戳信息,如果以某种方式重创错了,还可以拿回原始文件
content         # 取代src=,表示直接用此处指定的信息生成为目标文件内容;
dest=           # 远程节点存放文件的路径,必须是绝对路径
directory_mode  # 递归复制设置目录权限,默认为系统默认权限
force           # 如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果设置为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
group           # 复制到远程主机后,指定文件或目录的属
mode            # 复制到远程主机后,指定文件或目录权限,类似与 `chmod'指明如 0644
owner           # 复制到远程主机后,指定文件或目录属主
src             # 要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用"/"来结尾,则只复制目录里的内容,如果没有使用"/"来结尾,则包含目录在内的整个内容全部复制,类似于rsync。 

示例

  • 将本地的/etc/fstab文件复制到目标主机的/tmp/fstab.ansbile,属主为root权限为640
[root@ansible ~]#ansible websrv -m copy -a 'src=/etc/fstab dest=/tmp/fstab.ansible mode=640'
172.20.54.3 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "533c326f3c3654b97e826cf7b942a855de096969", 
    "dest": "/tmp/fstab.ansible", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "dec527a553b1dbd9c9518d966a81e30e", 
    "mode": "0640", 
    "owner": "root", 
    "size": 595, 
    "src": "/root/.ansible/tmp/ansible-tmp-1575796184.03-84641622955757/source", 
    "state": "file", 
    "uid": 0
}
[root@ansible ~]#ansible websrv -a 'ls /tmp/fstab.ansible -l'
172.20.54.4 | CHANGED | rc=0 >>
-rw-r----- 1 root root 595 Dec  8 17:09 /tmp/fstab.ansible
  • 在webserver组主机创建文件,自己手动指定文件内容
[root@ansible ~]#ansible websrv -m copy -a 'content="hello,world!\n" dest=/tmp/hello.txt'
172.20.54.4 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "8e41fa769f837c3cd5edec26f22c9e846e1d1dff", 
    "dest": "/tmp/hello.txt", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "abdb60390ee5dcf80db30b45433551a7", 
    "mode": "0644", 
    "owner": "root", 
    "size": 13, 
    "src": "/root/.ansible/tmp/ansible-tmp-1575796437.85-106616853454191/source", 
    "state": "file", 
    "uid": 0
[root@ansible ~]#ansible websrv -a 'cat /tmp/hello.txt'
172.20.54.4 | CHANGED | rc=0 >>
hello,world!
  • 使用backup选项
#如目标存在,默认覆盖,此处指定先备份
ansible srv -m copy -a “src=/root/test1.sh dest=/tmp/test2.sh owner=wang
mode=600 backup=yes”
#复制/etc/下的文件,不包括/etc/目录自身
ansible srv -m copy -a “src=/etc/ dest=/backup”

File模块

  • 功能:设置文件属性
[root@node1 ~]# ansible-doc -s file
- name: 设置文件属性
action: file
force          # 需要在两种情况下强制创建软连接,一种是源文件不存在但之后会建立的情况下;另一种是目标连接已存在,需要先取消之前的软连接,有两个选项:yes|no
group          # 设置文件或目录的属组,后面可以加上mode:定义文件/目录的权限
mode           # 设置文件或目录的权限
owner          # 设置文件或目录的属主,后面必须跟上path:定义文件/目录的路径
path=          # 必选项,定义文件或目录的路径
recurse        # 递归设置文件的属性,只对目录有效
src            # 要被链接到的路径,只应用与state=link的情况
dest         #被链接到的路径,只应用于state=link的情况
state          # directory:如果目录不存在,创建目录;
    file:即使文件不存在,也不会被创建   
    link:创建软连接;
    hard:创建硬连接;
    touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
    absent:删除目录、文件或者取消链接文件

示例

  • 设置/tmp/fstab.ansbile属主和属组都为mysql,权限为644
[root@ansible ~]#ansible websrv -m file -a 'path=/tmp/fstab.ansible owner=mysql mode=640 group=mysql'
172.20.54.3 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 996, 
    "group": "mysql", 
    "mode": "0640", 
    "owner": "mysql", 
    "path": "/tmp/fstab.ansible", 
    "size": 595, 
    "state": "file", 
    "uid": 998
}

172.20.54.3 | CHANGED | rc=0 >>
-rw-r----- 1 mysql mysql 595 Dec  8 17:09 /tmp/fstab.ansible
  • 在webserver组创建/test/fstab.ansible的连接文件
[root@ansible ~]#ansible websrv -m file -a 'src=/tmp/fstab.ansible dest=/tmp/fstab.link state=link'
172.20.54.3 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp/fstab.link", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 18, 
    "src": "/tmp/fstab.ansible", 
    "state": "link", 
    "uid": 0
}
[root@ansible ~]#ansible websrv -a 'ls -l /tmp/fstab*'
172.20.54.4 | CHANGED | rc=0 >>
-rw-r----- 1 root root 595 Dec  8 17:09 /tmp/fstab.ansible
lrwxrwxrwx 1 root root  18 Dec  8 17:46 /tmp/fstab.link -> /tmp/fstab.ansible
  • 创建并删除空文件
ansible srv -m file -a 'path=/data/test.txt state=touch'
ansible srv -m file -a 'path=/data/test.txt state=absent'
ansible srv -m file -a "path=/root/test.sh owner=wang mode=755
  • 创建并删除空目录
[root@ansible ~]#ansible websrv -m file -a "path=/tmp/mysql state=directory owner=mysql group=mysql"
172.20.54.3 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 996, 
    "group": "mysql", 
    "mode": "0755", 
    "owner": "mysql", 
    "path": "/tmp/mysql", 
    "size": 6, 
    "state": "directory", 
    "uid": 998
}
[root@ansible ~]#ansible websrv -a 'ls -l /tmp/mysql/ -d'
172.20.54.3 | CHANGED | rc=0 >>
drwxr-xr-x 2 mysql mysql 6 Dec  8 17:56 /tmp/mysql/
/ 删除此目录
[root@ansible ~]#ansible websrv -m file -a 'path=/tmp/mysql state=absent'
172.20.54.3 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/tmp/mysql", 
    "state": "absent"
}
[root@ansible ~]#ansible websrv -a 'ls -l /tmp'
172.20.54.3 | CHANGED | rc=0 >>
total 16
drwx------ 2 root  root   41 Dec  8 17:59 ansible_command_payload_M_jyx1
-rw-r--r-- 1 root  root   53 Dec  8 17:28 ceshi.sh
-rw-r----- 1 mysql mysql 595 Dec  8 17:09 fstab.ansible
lrwxrwxrwx 1 root  root   18 Dec  8 17:46 fstab.link -> /tmp/fstab.ansible
-rw-r--r-- 1 root  root   13 Dec  8 17:13 hello.txt
-rw-r--r-- 1 root  root   23 Dec  5 19:39 issue

unarchive模块

  • 功能:解包解压缩
  • 实现有两种用法:
    1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes
    2、将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no
  • 常见参数
copy:在解压文件之前,是否先将文件复制到远程主机,默认为yes。若为no,则要求目标主机上压缩包必须存在。
creates:指定一个文件名,当该文件存在时,则解压指令不执行
dest:远程主机上的一个路径,即文件解压的路径 
grop:解压后的目录或文件的属组
list_files:如果为yes,则会列出压缩包里的文件,默认为no,2.0版本新增的选项
mode:解决后文件的权限
src:如果copy为yes,则需要指定压缩文件的源路径 
owner:解压后文件或目录的属主
  • 注意:要传输解压缩的文件必须是tar归档文件之后的各种压缩格式,单独的压缩文件,这个模块不支持
  • 示例
  • 把ansible主机本地文件推送到远程主机并解压
[root@ansible ~]#ansible websrv -m unarchive -a 'src=/root/hello.tar.gz dest=/tmp/'
172.20.54.3 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/tmp/", 
    "extract_results": {
        "cmd": [
            "/usr/bin/gtar", 
            "--extract", 
            "-C", 
            "/tmp/", 
            "-z", 
            "-f", 
            "/root/.ansible/tmp/ansible-tmp-1575808678.08-128025411979564/source"
        ], 
        "err": "", 
        "out": "", 
        "rc": 0
    }, 
    "gid": 0, 
    "group": "root", 
    "handler": "TgzArchive", 
    "mode": "01777", 
    "owner": "root", 
    "size": 254, 
    "src": "/root/.ansible/tmp/ansible-tmp-1575808678.08-128025411979564/source", 
    "state": "directory", 
    "uid": 0
}
  • 解压远程主机tar归档文件
    [root@ansible ~]#ansible testsrv -m unarchive -a 'src=/tmp/fstab.tar dest=/tmp copy=no'

Archive模块

  • 功能:打包压缩
  • 范例
    ansible testsrv -m archive -a 'path=/var/log dest=/tmp/log.tar.bz2 format=bz2 owner=yijie mode=700'

Hostname模块

  • 功能:管理主机名,而且是修改文件内容生效,不是临时设置
  • 范例
ansible testsrv -m hostname -a 'name="test001"'
ansible 172.20.54.3 -m hostname -a 'name="test002"'

Cron模块

  • 功能:计划任务
  • 支持时间minutehourdaymonthweekday
  • 常用参数
- name: 设置管理节点生成定时任务
action: cron
backup             # 如果设置,创建一个crontab备份
cron_file          #如果指定, 使用这个文件cron.d,而不是单个用户crontab
day                # 日应该运行的工作( 1-31, *, */2, etc )
hour               # 小时 ( 0-23, *, */2, etc )
job                #指明运行的命令是什么
minute             #分钟( 0-59, *, */2, etc )
month              # 月( 1-12, *, */2, etc )
name               #定时任务描述
reboot             # 任务在重启时运行,不建议使用,建议使用special_time
special_time       # 特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)
state              #指定状态,prsent表示添加定时任务,也是默认设置,absent表示删除定时任务
user               # 以哪个用户的身份执行
weekday            # 周 ( 0-6 for Sunday-Saturday, *, etc )
  • 示例:
/ 创建备份数据库脚本
[root@ansible ~]#vim mysql_backup.sh
#!/bin/bash
mysqldump -uroot -ppassword -A -F --single-transaction --master-data=2 | gzip> /data/mysql_`date +%F_%T`.sql.gz
/ 创建任务
[root@ansible ~]#ansible testsrv -m cron -a 'hour=2 minute=30 weekday=1-5 name="mysql" job=/root/mysql_backup.sh'
/ 查看任务
[root@ansible ~]#ansible testsrv -a 'crontab -l'
172.20.54.3 | CHANGED | rc=0 >>
#Ansible: mysql
30 2 * * 1-5 /root/mysql_backup.sh
/ 禁用任务
[root@ansible ~]#ansible testsrv -m cron -a 'hour=2 minute=30 weekday=1-5 name="mysql" job=/root/mysql_backup.sh disabled=yes'
/ 查看任务
[root@ansible ~]#ansible testsrv -a 'crontab -l'
172.20.54.3 | CHANGED | rc=0 >>
#Ansible: mysql
#30 2 * * 1-5 /root/mysql_backup.sh    / 被注释掉了
/ 启用任务
[root@ansible ~]#ansible testsrv -m cron -a 'hour=2 minute=30 weekday=1-5 name="mysql" job=/root/mysql_backup.sh disabled=no'
/ 删除任务
[root@ansible ~]#ansible testsrv -m cron -a 'name="mysql" state=absent'

Yum模块

  • 功能:管理软件包
  • 常用参数
conf_file          # yum的配置文件
disable_gpg_check  # 关闭gpg_check
disablerepo        # 不启用某个源
enablerepo         # 启用某个源
name=              # 指定要安装的包,如果有多个版本需要指定版本,否则安装最新的包
state              # 安装(`present'),安装最新版(`latest'),卸载程序包(`absent')
  • 范例
/ 安装httpd
ansible testsrv -m yum -a 'name=httpd state=present'
/ 卸载httpd
ansible testsrv -m yum -a 'name=httpd state=absent'

Service模块

  • 功能:管理服务
  • 常用参数
action: service
arguments     # 向服务传递的命令行参数
enabled       # 设置服务开机自动启动,参数为yes|no
name=         # 控制服务的名称
pattern       # 定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行
runlevel      # 设置服务自启动级别
sleep         # 如果执行了restarted,则在stop和start之间沉睡几秒钟
state         # 启动`started' 关闭`stopped' 重新启动 `restarted' 重载 `reloaded'
  • 范例
/ 启动服务并设为开机启动
ansible testsrv -m service -a 'name=httpd enabled=yes state=started'
/ 停止服务
ansible testsrv -m service -a 'name=httpd state=stopped'
/ 重装服务
ansible testsrv -m service -a 'name=httpd state=reloaded'
/ 修改配置文件然后重启服务
ansible testsrv -m shell -a "sed -i 's/^Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf"
ansible testsrv -m service -a 'name=httpd stated=restarted'

User模块

  • 功能:管理用户
  • 常见参数
comment          # 用户的描述信息
createhome       # 是否创建家目录
force            # 在使用`state=absent'是, 行为与`userdel --force'一致.
group            # 指定基本组
groups           # 指定附加组,如果指定为('groups=')表示删除所有组
home             # 指定用户家目录
login_class      #可以设置用户的登录类 FreeBSD, OpenBSD and NetBSD系统.
move_home        # 如果设置为`home='时, 试图将用户主目录移动到指定的目录
name=            # 指定用户名
non_unique       # 该选项允许改变非唯一的用户ID值
password         # 指定用户密码
remove           # 在使用 `state=absent'时, 行为是与 `userdel --remove'一致.
shell            # 指定默认shell
state            #设置帐号状态,不指定为创建,指定值为absent表示删除
system           # 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户。
uid              #指定用户的uid
update_password  # 更新用户密码
  • 范例
/ 创建用户
ansible testsrv -m user -a 'name=user1 comment="test user" uid=2048 home=/data/user1 group=root'
/ 创建系统用户 不需要用户家目录
ansible testsrv -m user -a 'name=nginx comment=nginx uid=88   
shell=/sbin/nologin non_unique=yes create_home=no system=yes'
/ 删除指定用户nginx
ansible testsrv -m user -a 'name=nginx state=absent'

Group模块

  • 功能:管理组
  • 常用参数
gid       # 设置组的GID号
name=     # 管理组的名称
state     # 指定组状态,默认为创建,设置值为absent为删除
system    # 设置值为yes,表示为创建系统组
  • 范例
/ 创建用户组
ansible testsrv -m group -a 'name=nginx gid=88 system=yes'
/ 删除用户组
ansible testsrv -m group -a 'name=nginx state=absent'

Setup模块

功能:返回系统状态信息

ansible srv -m setup
ansible srv -m setup -a "filter=ansible_nodename"
ansible srv -m setup -a "filter=ansible_hostname"
ansible srv -m setup -a "filter=ansible_domain"
ansible srv -m setup -a "filter=ansible_memtotal_mb"
ansible srv -m setup -a "filter=ansible_memory_mb"
ansible srv -m setup -a "filter=ansible_memfree_mb"
ansible srv -m setup -a "filter=ansible_os_family"
ansible srv -m setup -a "filter=ansible_distribution_major_version"
ansible srv -m setup -a "filter=ansible_distribution_version"
ansible srv -m setup -a "filter=ansible_processor_vcpus"
ansible srv -m setup -a "filter=ansible_all_ipv4_addresses"
ansible srv -m setup -a "filter=ansible_architecture"

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值