自动化运维--ansible

ansible

1.ansible是什么?

   ansible是一个基于Python开发的自动化运维工具 !

   其功能实现基于SSH远程连接服务!

   ansible可以实现批量系统配置、批量软件部署、批量文件拷贝、批量运行命令等功能

2.ansible软件特性

   不需要单独安装客户端(no agents),基于系统自带的sshd服务,sshd就相当于ansible的客户端。
 
   不需要服务端(no servers)。

   需要依靠大量的模块实现批量管理。? 

   配置文件/etc/ansible/ansible.cfg,不用配置

3.ansible软件执行结果

   输出内容显示绿色:表示执行成功,当没有任何改变

   输出内容显示黄色:表示执行成功,但对被管理主机进行了改变

   输出内容显示红色:表示执行失败

ansible模块

command模块

command :作为ansible的默认模块,可以允许远程主机范围内的所有shell命令。

script模块

功能:在远程主机上执行主控端的脚本,相当于scp+shell组合。

shell模块

功能:执行远程主机的shell脚本文件

copy模块

功能: 实现主控端向目标主机copy文件。

stat模块

功能: 获取远程文件的状态信息,包括atime,ctime,mtime,md5,uid,gid等信息。

yum模块

功能: 安装软件包。

cron模块

功能:远程主机crontab配置

template模块

基于模板方式生成一个文件复制到远程主机(template使用Jinjia2格式作为文件模版,进行文档内变量的替换的模块。它的每次使用都会被ansible标记为”changed”状态。)

安装部署ansible

1.安装

[root@server1 ~]# cd ansible/
[root@server1 ansible]# ls
ansible-2.7.8-1.el7.noarch.rpm
ansible-tower-setup-bundle-3.4.2-1.el7.tar.gz
libtomcrypt-1.17-25.el7.x86_64.rpm
libtommath-0.42.0-5.el7.x86_64.rpm
python2-crypto-2.6.1-13.el7.x86_64.rpm
python2-jmespath-0.9.0-1.el7.noarch.rpm
python-httplib2-0.9.2-0.1.el7.noarch.rpm
python-keyczar-0.71c-2.el7.noarch.rpm
python-paramiko-2.1.1-0.9.el7.noarch.rpm
roles
sshpass-1.06-1.el7.x86_64.rpm
[root@server1 ansible]# yum install -y *.rpm

2.创建devops用户,设置ansible服务的组和组里的主机

[root@server1 ansible]# cd /etc/ansible/
[root@server1 ansible]# ls
ansible.cfg  hosts  roles
[root@server1 ansible]# useradd devops
[root@server1 ansible]# passwd devops
Changing password for user devops.
New password: 
BAD PASSWORD: The password is shorter than 8 characters
Retype new password: 
passwd: all authentication tokens updated successfully.
[root@server1 ansible]# su - devops
[devops@server1 ~]$ mkdir ansible
[devops@server1 ~]$ cd ansible/
[devops@server1 ansible]$ vim ansible.cfg
[devops@server1 ansible]$ cat ansible.cfg 
[defaults]

inventory	= inventory
[devops@server1 ansible]$ vim inventory
[devops@server1 ansible]$ cat inventory 
[test]									##定义主机组
server2							##主机名

[db]
server3

[webservers:children]
test
db

3.制作免密连接

server2 server3
[root@server2 ~]# useradd devops
[root@server2 ~]# passwd devops

server1
[devops@server1 ansible]$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/devops/.ssh/id_rsa): 
Created directory '/home/devops/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/devops/.ssh/id_rsa.
Your public key has been saved in /home/devops/.ssh/id_rsa.pub.
The key fingerprint is:
5c:10:24:a3:75:12:6a:18:7d:ff:0e:29:4e:e8:9e:65 devops@server1
The key's randomart image is:
+--[ RSA 2048]----+
|  ..  *o=.       |
|   o.+.= .       |
|  . +. .  .      |
|   .   ...       |
|     .  So       |
|    . o o .      |
|   . oE. o       |
|    .+.   .      |
|   .o            |
+-----------------+
[devops@server1 ansible]$ ssh-copy-id server1
[devops@server1 ansible]$ ssh-copy-id server2
[devops@server1 ansible]$ ssh-copy-id server3

4.免密连接测试

[devops@server1 ansible]$ ansible all --list-hosts
  hosts (2):
    server3
    server2
[devops@server1 ansible]$ ansible all -m ping
server2 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
server3 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
[devops@server1 ansible]$ ansible all -m setup			##查看主机组里面所有主机的配置信息

5.使用copy模块

test表示的是组,在inventory里写了,所以操作的是server2,-m 表示的指定模块 -a指定后面的动作

[devops@server1 ansible]$ ansible test -m copy -a 'src=/etc/passwd dest=/tmp/passwd'
server2 | CHANGED => {
    "changed": true, 
    "checksum": "22dc9c5c3e860a79ca8a2328cd2fb7ab5ebba3d1", 
    "dest": "/tmp/passwd", 
    "gid": 1000, 
    "group": "devops", 
    "md5sum": "0471aa190bc587c20bffa116275b43c2", 
    "mode": "0664", 
    "owner": "devops", 
    "size": 1003, 
    "src": "/home/devops/.ansible/tmp/ansible-tmp-1560144902.87-50483023420876/source", 
    "state": "file", 
    "uid": 1000
}

server2查看

[root@server2 ~]# su - devops
Last login: Mon Jun 10 13:35:47 CST 2019 on pts/0
[devops@server2 ~]$ ll /tmp/passwd 
-rw-rw-r-- 1 devops devops 1003 Jun 10 13:35 /tmp/passwd
[devops@server2 ~]$ cat /tmp/passwd 

server1

[devops@server1 ansible]$ ansible test -a 'ls -l /tmp/passwd'
server2 | CHANGED | rc=0 >>
-rw-rw-r-- 1 devops devops 1003 Jun 10 13:35 /tmp/passwd

[devops@server1 ansible]$ ansible test -a 'ls /tmp/passwd'
server2 | CHANGED | rc=0 >>
/tmp/passwd

##使用file模块
[devops@server1 ansible]$ ansible test -m file -a 'dest=/tmp/passwd mode=600'
server2 | CHANGED => {
    "changed": true, 
    "gid": 1000, 
    "group": "devops", 
    "mode": "0600", 
    "owner": "devops", 
    "path": "/tmp/passwd", 
    "size": 1003, 
    "state": "file", 
    "uid": 1000
}
[devops@server1 ansible]$ ansible test -a 'ls -l /tmp/passwd'
server2 | CHANGED | rc=0 >>
-rw------- 1 devops devops 1003 Jun 10 13:35 /tmp/passwd

6.添加用户授权,让普通用户能够执行超级用户的一些权限

server2 server3
[root@server3 ~]# vim /etc/sudoers
devops  ALL=(ALL)       NOPASSWD: ALL

ansible自动安装httpd

1.使用yum模块,给test组里的主机安装httpd

[devops@server1 ansible]$ ansible test -m yum -a 'name=httpd state=present' -b
[devops@server1 ansible]$ ansible test -a 'rpm -q httpd'				##查看

2.取消-b参数

[devops@server1 ansible]$ vim ansible.cfg 
[devops@server1 ansible]$ cat ansible.cfg 
[defaults]

inventory	= inventory

[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
[devops@server1 ansible]$ ansible test -m yum -a 'name=httpd state=present'

3.给webservers包含的组的所有主机安装httpd

[devops@server1 ansible]$ ansible webservers -m yum -a 'name=httpd state=present'

在这里插入图片描述

4.卸载test组里所有主机的httpd服务

[devops@server1 ansible]$ ansible test -m yum -a 'name=httpd state=absent'
[devops@server1 ansible]$ ansible test -a 'rpm -q htppd'

5.开启服务

[devops@server1 ansible]$ curl server3
curl: (7) Failed connect to server3:80; Connection refused
[devops@server1 ansible]$ ansible db -m service -a 'name=httpd state=started'
[devops@server1 ansible]$ curl server3

6.发布默认发布页

[devops@server1 ansible]$ ansible db -m copy -a 'content="www.dzh.org\n" dest=/var/www/html/index.html'
server3 | CHANGED => {
    "changed": true, 
    "checksum": "9e463c3c1e487f724201c2062c64f06df14357df", 
    "dest": "/var/www/html/index.html", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "1f29c821a7f609fc4fc2cc0e65cfbba3", 
    "mode": "0644", 
    "owner": "root", 
    "size": 12, 
    "src": "/home/devops/.ansible/tmp/ansible-tmp-1560253589.01-78653058950786/source", 
    "state": "file", 
    "uid": 0
}

[devops@server1 ansible]$ curl server3
www.dzh.org

7.开启防火墙并设置火墙允许httpd服务通过

[devops@server1 ansible]$ ansible db -m service -a 'name=firewalld state=started enabled=true'
[devops@server1 ansible]$ curl server3
curl: (7) Failed connect to server3:80; No route to host

[devops@server1 ansible]$ ansible db -m firewalld -a 'service=http state=enabled permanent=yes immediate=yes'
server3 | CHANGED => {
    "changed": true, 
    "msg": "Permanent and Non-Permanent(immediate) operation, Changed service http to enabled"
}
[devops@server1 ansible]$ curl server3
www.dzh.org

8.设置tab键的空格数目

[devops@server1 ansible]# cat ~/.vimrc
autocmd filetype yaml setlocal ai ts=2 sw=2 et

自动部署httpd服务

1.创建存放httpd.conf的目录

[devops@server1 ansible]$ mkdir files
[devops@server1 ansible]$ cd files/
[devops@server1 files]$ scp server3:/etc/httpd/conf/httpd.conf .
httpd.conf       

2.编写playbook.yml

[devops@server1 ansible]$ vim playbook.yml
---
# deploy apache
- hosts: webservers
  tasks:
    - name: install httpd
      yum:
        name: httpd
        state: latest

    - name: create index.html
      copy:
        content: "www.westos.org\n"
        dest: /var/www/html/index.html

    - name: configure httpd
      copy:
        src: files/httpd.conf
        dest: /etc/httpd/conf/httpd.conf
        owner: root
        group: root
        mode: 644
      notify: restart httpd			##设置触发器,如果更改了httpd.conf就触发

    - name: start httpd
      service:
        name: httpd
        state: started
        enabled: true

  handlers:					##name一定要和notify后面的一致
    - name: restart httpd
      service:
	name: httpd
        state: restarted

在这里插入图片描述

3.执行playbook.yml


[devops@server1 ansible]$ ansible-playbook playbook.yml --syntax-check		#检查语法

playbook: playbook.yml

执行
[devops@server1 ansible]$ ansible-playbook playbook.yml

4.测试

[devops@server1 ansible]$ curl server2
www.dzh.org
[devops@server1 ansible]$ curl server3
www.dzh.org

5.更改配置文件,将端口设置成8080再测试

[devops@server1 ansible]$ md5sum files/httpd.conf 
f5e7449c0f17bc856e86011cb5d152ba  files/httpd.conf

[devops@server1 ansible]$ vim files/httpd.conf
Listen 8080

[devops@server1 ansible]$ md5sum files/httpd.conf 
04e9239e7bd5d5b9b85864226d60eee5  files/httpd.conf

[devops@server1 ansible]$ ansible-playbook playbook.yml




[devops@server2 ~]$ netstat -ntlp
(No info could be read for "-p": geteuid()=1000 but you should be root.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      -                   
tcp6       0      0 :::8080                 :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       0      0 ::1:25                  :::*                    LISTEN      -                  

在这里插入图片描述
6.添加防火墙

[devops@server1 ansible]$ vim playbook.yml
- name: start firewalld				##开启火墙
    service:
      name: firewalld
      state: started
      enabled: true

- name: configure firewalld			##允许http服务可以通过火墙
   firewalld:
      service: http
      state: enabled
      permanent: yes
      immediate: yes

  handlers:
    - name: restart httpd
      service:
        name: httpd
        state: restarted
[devops@server1 ansible]$ ansible-playbook playbook.yml --syntax-check
[devops@server1 ansible]$ ansible-playbook playbook.yml				##注意files/httpd.conf端口要改回80
[devops@server1 ansible]$ curl server2
www.dzh.org
[devops@server1 ansible]$ curl server3
www.dzh.org
且server2 server3的火墙都开启了
[devops@server2 ~]$ systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2019-06-11 20:26:44 CST; 2min 21s ago
     Docs: man:firewalld(1)
 Main PID: 4690 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─4690 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

在这里插入图片描述

7.变量名–主机名

[devops@server1 ansible]$ vim playbook.yml 
- name: create index.html
  copy:
    content: "{{ ansible_facts['hostname'] }}\n"		##或者ansible_facts.hostname
    dest: /var/www/html/index.html
[devops@server1 ansible]$ ansible-playbook playbook.yml
[devops@server1 ansible]$ curl server2
server2
[devops@server1 ansible]$ curl server3
server3

在这里插入图片描述

8.变量名–ip

[devops@server1 ansible]$ ansible webservers -m setup | less		##查看信息
"ansible_default_ipv4": {
            "address": "172.25.68.2", 
            "alias": "eth0", 
            "broadcast": "172.25.68.255", 
            "gateway": "172.25.68.250", 
            "interface": "eth0", 
            "macaddress": "52:54:00:1d:0e:a6", 
            "mtu": 1500, 
            "netmask": "255.255.255.0", 
            "network": "172.25.68.0", 
            "type": "ether"
            
[devops@server1 ansible]$ vim playbook.yml
- name: create index.html
      copy:
        content: "{{ ansible_facts['hostname'] }} {{ ansible_facts['default_ipv4']['address'] }}\n"
        dest: /var/www/html/index.html
[devops@server1 ansible]$ ansible-playbook playbook.yml
[devops@server1 ansible]$ curl server2
server2 172.25.68.2
[devops@server1 ansible]$ curl server3
server3 172.25.68.3

在这里插入图片描述

9.标记–只执行那一个模块

[devops@server1 ansible]$ vim playbook.yml
- name: create index.html
  copy:
    content: "{{ ansible_facts['hostname'] }} {{ ansible_facts['default_ipv4']['address'] }}\n"
    dest: /var/www/html/index.html
  tags: one

[devops@server1 ansible]$ ansible-playbook playbook.yml -t one

在这里插入图片描述

模板j2

1.使用模板模块

[devops@server1 ansible]$ cd files/
[devops@server1 files]$ mv httpd.conf httpd.conf.j2
[devops@server1 ansible]$ vim playbook.yml

- hosts: webservers
  vars:
    http_port: 80


    - name: configure httpd
      template:					        ##模板模块
        src: files/httpd.conf.j2
        dest: /etc/httpd/conf/httpd.conf
        owner: root
        group: root
        mode: 644
      notify: restart httpd

[devops@server1 ansible]$ vim files/httpd.conf.j2
Listen {{ http_port }}

[devops@server1 ansible]$ ansible-playbook playbook.yml

2.模板

[devops@server1 ansible]$ mkdir templates
[devops@server1 ansible]$ vim playbook.yml
- name: configure httpd
      template:
        src: templates/httpd.conf.j2
        dest: /etc/httpd/conf/httpd.conf
        owner: root
        group: root
        mode: 644
      notify: restart httpd
[devops@server1 ansible]$ cp files/httpd.conf.j2 templates/

3.使用模板创建包含主机一些信息的文件

[devops@server1 ansible]$ vim hostinfo.yml
---
- hosts: all
  tasks:
    - name: create infofile
      template:
        src: templates/info.j2
        dest: /mnt/hostinfo
[devops@server1 ansible]$ cd templates/
[devops@server1 templates]$ vim info.j2
主机名: {{ ansible_facts['hostname'] }}
主机IP地址: {{ ansible_facts['default_ipv4']['address'] }}
根分区大小: {{ ansible_facts['devices']['dm-0']['size'] }}
系统内核: {{ ansible_facts['distribution_version'] }}
[devops@server1 ansible]$ ansible-playbook hostinfo.yml --syntax-check

playbook: hostinfo.yml
[devops@server1 ansible]$ ansible-playbook hostinfo.yml

在这里插入图片描述

4.测试

[devops@server1 ansible]$ ansible all -a 'ls -l /mnt/hostinfo'
server2 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 90 Jun 11 23:34 /mnt/hostinfo

server3 | CHANGED | rc=0 >>
-rw-r--r-- 1 root root 90 Jun 11 23:34 /mnt/hostinfo

[devops@server1 ansible]$ ansible all -a 'cat /mnt/hostinfo'
server3 | CHANGED | rc=0 >>
主机名: server3
主机IP地址: 172.25.68.3
根分区大小: 9.79 GB
系统内核: 7.3

server2 | CHANGED | rc=0 >>
主机名: server2
主机IP地址: 172.25.68.2
根分区大小: 9.79 GB
系统内核: 7.3

在这里插入图片描述

指定主机安装
[devops@server1 ansible]$ vim install.yml
---
- hosts: all
  tasks:
    - name: install pkgs
      yum:
        name: "{{ item }}"
        state: present
      when: ansible_facts['hostname'] == 'server2'					##指定server2主机
      loop:
        - httpd
        - mariadb
        - php
        - php-mysql

    - name: install mariadb
      yum:
        name: mariadb
        state: present
      when: ansible_facts['hostname'] == 'server3'					##指定server3主机
[devops@server1 ansible]$ ansible-playbook install.yml --syntax-check

playbook: install.yml
[devops@server1 ansible]$ ansible-playbook install.yml

在这里插入图片描述

循环
/etc/hosts
[devops@server1 ansible]$ vim hostinfo.yml
---
- hosts: all
  tasks:
#    - name: create infofile
#      template:
#        src: templates/info.j2
#       dest: /mnt/hostinfo

    - name: create hosts
      template:
        src: templates/hosts.j2
        dest: /etc/hosts
        owner: root
        group: root
        mode: 0644
        
[devops@server1 ansible]$ vim templates/hosts.j2
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for host in groups['webservers'] %}						##循环
{{ hostvars[host]['ansible_facts']['eth0']['ipv4']['address'] }} {{ hostvars[host]['ansible_facts']['hostname'] }}
{% endfor %}

[devops@server1 ansible]$ vim inventory 
[devops@server1 ansible]$ cat inventory 
[test]
server2
server1

[db]
server3

[webservers:children]
test
db

[root@server1 ansible]# vim /etc/sudoers
devops  ALL=(ALL)       NOPASSWD: ALL

在这里插入图片描述

在这里插入图片描述

[devops@server1 ansible]$ ansible-playbook hostinfo.yml
[devops@server1 ansible]$ cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.68.3 server3
172.25.68.2 server2
172.25.68.1 server1
批量添加用户
[devops@server1 ansible]$ vim adduser.yml 
---
- hosts: all
  vars_files:
    - vars/userlist.yml
  tasks:
    - name: create users
      user:
        name: "{{ item.user }}"
        state: present
        password: "{{ item.pass }}"
      loop: "{{ userlist }}"
[devops@server1 ansible]$ mkdir vars
[devops@server1 ansible]$ cd vars/
[devops@server1 vars]$ vim userlist.yml
[devops@server1 vars]$ ansible-vault encrypt userlist.yml 
New Vault password: 
Confirm New Vault password: 
Encryption successful
[devops@server1 vars]$ cat userlist.yml 
$ANSIBLE_VAULT;1.1;AES256
31633137363733316630303239353338313164373462306434363036646233663963663135646565
3332376232656438393332643363663366636466653661350a623234376334356439616337313738
62643231343066306662353365356263646661333738373031326263393561643830333763303430
3533386433626630630a616338653432373832393030363166653765303362303437633938383662
33303231303937316664373435643731643535666230366638393839323835343266333231646135
37363432313737353565386138326264633430333466346639616537303634373038666234393564
66313263353166623733306661613461343034353365363630326638396339623532313533633632
63383662343462336564366438656339663635643334316437363832306566346230643332366439
6661
[devops@server1 vars]$ ansible-vault view userlist.yml 	       ##此时需要密码才能查看
Vault password: 
---
userlist:
  - user: user1
    pass: westos
  - user: user2
    pass: redhat

在这里插入图片描述

[devops@server1 ansible]$ ansible-playbook adduser.yml --ask-vault-pass
Vault password: 

PLAY [all] *****************************************************************************

TASK [Gathering Facts] *****************************************************************
ok: [server3]
ok: [server2]

TASK [create users] ********************************************************************
changed: [server3] => (item={u'user': u'user1', u'pass': u'westos'})
changed: [server2] => (item={u'user': u'user1', u'pass': u'westos'})
changed: [server3] => (item={u'user': u'user2', u'pass': u'redhat'})
 [WARNING]: The input password appears not to have been hashed. The 'password' argument
must be encrypted for this module to work properly.

changed: [server2] => (item={u'user': u'user2', u'pass': u'redhat'})

PLAY RECAP *****************************************************************************
server2                    : ok=2    changed=1    unreachable=0    failed=0   
server3                    : ok=2    changed=1    unreachable=0    failed=0 



[root@server2 ~]# cat /etc/shadow		##密码还是明文
user1:westos:18060:0:99999:7:::
user2:redhat:18060:0:99999:7:::

在这里插入图片描述
在这里插入图片描述

[devops@server1 ansible]$ vim adduser.yml 
---
- hosts: all
  vars_files:
    - vars/userlist.yml
  tasks:
    - name: create users
      user:
        name: "{{ item.user }}"
        state: present
        password: "{{ item.pass | password_hash('sha512','mysecretslat') }}"
      loop: "{{ userlist }}"
[devops@server1 ansible]$ ansible-playbook adduser.yml --ask-vault-pass
Vault password: 

PLAY [all] **********************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [server2]
ok: [server3]

TASK [create users] *************************************************************************************************
changed: [server2] => (item={u'user': u'user1', u'pass': u'westos'})
changed: [server3] => (item={u'user': u'user1', u'pass': u'westos'})
changed: [server3] => (item={u'user': u'user2', u'pass': u'redhat'})
changed: [server2] => (item={u'user': u'user2', u'pass': u'redhat'})

PLAY RECAP **********************************************************************************************************
server2                    : ok=2    changed=1    unreachable=0    failed=0   
server3                    : ok=2    changed=1    unreachable=0    failed=0  



[root@server2 ~]# cat /etc/shadow						##密码变成密文
user1:$6$mysecretslat$9BHrNJOamAqTfgPjfgMF67trp.8CVN4CXq/.btQ2lNTq8YNCGZKRBzLiShaGDT.xtXqU.TE/rMPxyBNbnSsjG1:18060:0:99999:7:::
user2:$6$mysecretslat$u1GP1.iBm2lsLHWzzqgSMx7ivazVxB3l3iSSgTkAN.B.PBD1NVvbwzzECjkErIeHpv9jfpczEFTgdUy.xXLyl0:18060:0:99999:7:::

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

删除用户

状态改为absent

[devops@server1 ansible]$ cat adduser.yml 
---
- hosts: all
  vars_files:
    - vars/userlist.yml
  tasks:
    - name: create users
      user:
        name: "{{ item }}"
        state: absent
        password: westos
      loop: "{{ userlist }}"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值