简介:

Ad-Hoc简而言之是“临时命令”,英文中作为形容词有“特别的”,“临时”的含义。

Ansible提供两种完成任务方式:一种是Ad-Hoc命令集,即命令ansible,另外一种就是Ansible-playbook了,即命令Ansible-playbook。

Ad-Hoc适合解决一些简单或者平时工作中临时遇到的任务

Ansible-playbook适合解决复杂或需固化下来的任务

深入Ansible是从接触Ansible-playbook开始的,灵活运用Ansible-playbook才能更好的体会到Ansible的强大所在。

Ad-Hoc命令集介绍

Ad-Hoc命令集由/usr/bin/ansible实现,其命令用法如下:

ansible  <host-pattern> [options]

可用选项如下:

-v,--verbose:输出更详细的执行过程信息,-vvv可得到执行过程所有信息。

-i,PATH,--inventory(清单)=PATH:指定inventory(清单)信息,默认/etc/ansible/hosts

-f NUM,--forks=NUM:并发线程数,默认5个线程。

--private-key=PRIVATE_KEY_FILE:指定密钥文件。

-m NMAE,--module-name=NAME:指定执行使用的模块。

-M DIRECTORY,--module-path=DIRECTORY:指定模块存放路径,默认/usr/share/ansible,也可以通过ANSIBLE_LIBRARY设定默认路径。

-a ‘ARGUMENTS’,--args=‘ARGUMENTS’:模块参数。

-k,--ask-pass SSH:认证密码

-K,--ask-sudo-pass sudo:用户的密码(--sudo时使用)。

-o,--one-line:标准输出至一行。

-s,--sudo:相当于Linux系统下的sudo命令。

-t DIRECTORY,--tree=DIRECTORY:输出信息至DIRECTORY目录下,结果文件以远程主机命名。

-T SECONDS,--timeout=SECONDS:指定连接远程主机的最大超时,单位是秒。

-B NUM,--background=NUM:后台执行命令,超NUM秒后中止正在执行的任务。

-P NUM,--poll=NUM:定期返回后台任务进度。

-u USERNAME,--user=USERNAME:指定远程主机以USERNAME运行命令。

-U SUDO_USERNAME,--sudo-user=SUDO_USERNAME:使用sudo,相当于LInux下的sudo命令。

-c CONNECTION,--connection=CONNECTION:指定连接方式,可用选项paramiko(SSH)、ssh、local,local方式常用于crontab和kickstarts。

-l  SUBSET,--limit=SUBSET:指定运行主机。

-l ~REGEX,--limit=~REGEX:指定运行主机(正则)。

--list-hosts:列出符合条件的主机列表,不执行任何命令。

实例:

(1.)检查proxy组所有主机是否存活。

执行命令:

ansible proxy -f 5 -m ping

返回结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_git

上述执行结果:

其中192.168.1.18是指命令执行的主机,Success表示命令执行成功,">>{}"表示详细返回结果如下。

"changed":false 表示没有对主机做变更"ping":"pong"表示执行了ping命令返回结果为pong。

(2.)返回proxy组所有主机的hostname,并打印最详细的执行过程到标准输出。

执行命令:

ansible proxy  -s  -m  command -a  'hostname'  -vvv

上述执行结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_shell_02

ESTABLISH CONNECTION FOR USER:root    :远程主机192.168.1.18监听用户root的22号端口

REMOTE_MODULE  command  hostname :远程执行命令hostname
"/bin/sh -c 'mkdir -p $HOME/.ansible/tmp/ansible-tmp-1537154337.4-134606313491356 && echo $HOME/.ansible/tmp/ansible-tmp-1537154337.4-134606313491356'"]  :生成临时目录用于存放Ansible远程执行脚本。
PUT /tmp/tmp4f_9zu TO /root/.ansible/tmp/ansible-tmp-1537154337.4-134606313491356/command :改名临时脚本并存放至临时目录。
EXEC ['ssh', '-C', '-tt', '-q', '-o', 'ControlMaster=auto', '-o', 'ControlPersist=60s', '-o', 'ControlPath=/root/.ansible/cp/ansible-ssh-%h-%p-%r', '-o', 'StrictHostKeyChecking=no', '-o', 'Port=22', '-o', 'IdentityFile="/root/.ssh/id_rsa_storm1"', '-o', 'KbdInteractiveAuthentication=no', '-o', 'PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey', '-o', 'PasswordAuthentication=no', '-o', 'ConnectTimeout=10', '192.168.1.18', u"/bin/sh -c 'LANG=en_US.UTF-8 LC_CTYPE=en_US.UTF-8 /usr/bin/python /root/.ansible/tmp/ansible-tmp-1537154337.4-134606313491356/command; rm -rf /root/.ansible/tmp/ansible-tmp-1537154337.4-134606313491356/ >/dev/null 2>&1'"] :使用sudo方式并以Python脚本方式执行命令。
192.168.1.18 | success | rc=0 >> :返回结果成功。

(3.)对192.168.1.18服务器以root执行sleep20,设置最大连接超时时间时长为2s,且设置为后台运行模式,执行过程没2s输出一次进度,如5s还未执行完则终止该任务。

执行命令:

time  ansible 192.168.1.18 -B 5 -P 2 -T 2 -m  command -a  'sleep 20'  -u  root

执行结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_git_03

  第一行:background launch...表示使用-B使该命令后台运行。

下面每隔2s输出一次执行进度

<job 628451417226.4601> polling, 3s remaining 表示执行时长剩余3s
下面每隔2s输出一次执行进度
<job 628451417226.4601> polling, 1s remaining 表示执行时长剩余1s
real    0m55.664s 程序执行总时长
 user    0m0.269s  系统用户层执行时长
 sys     0m0.118s   系统内核层执行时长

 

通过Ad-Hoc查看系统设置

接下来通过df、free命令查看系统设置,通过Ad-Hoc实现。

(1.)批量查看apps组所有主机的磁盘容量(使用command模块)。

执行命令:

ansible apps  -a  "df -lh"

返回结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_ansible_04

success表示执行成功

(2.)批量查看远程主机内存使用情况(shell模块)。

ansible apps -m shell  -a  "free -m "

返回结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_awk_05

通过Ad-Hoc研究Ansible的并发特性

ansible和Ansible-playbook默认会fork 5个线程并发执行命令,但在实际工作中,如果主机数量众多,Ansible并发5个线程是远不能满足企业所需的。

接下来我们定义[apps]组,多次执行同样的Ad-Hoc命令来查看其返回的结果。

(1.)定义[apps]组,编辑/etc/ansible/hosts的配置

[apps]
192.168.1.18
192.168.1.27
192.168.1.29
192.168.1.30

(2.)多次执行Ansible命令,执行命令如下:

ansible apps  -m  ping  -f 3

对比返回结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_shell_06

上述执行的结果分析如下:

同样的命令多次执行,但每次的输出结果都不一定一样。

输出结果是不是按照/etc/ansible/hosts中[apps]定义的主机顺序输出。

如果主机数量很多,我们需要调大线程数,该如何操作呢?这里ansible为我们提供了便捷的选项 ,-f指定线程数。

Ansible使用multiprocessing管理多线程。

通过Ad-Hoc研究Ansible的模块使用

接下来为大家介绍Ad-Hoc的模块使用。另外,Ansible也提供了类似于man功能的help说明工具ansible-doc。

正式学习Ansible模块使用前,有必要先了解ansible-doc用法

命令用法:

ansible-doc  [options]  [module...]

可用选项如下:

--version:显示工具版本号

-h,--help:显示该help说明。

-M MODULE_PATH,--module-path=MODULE_PATH:指定Ansible模块的默认加载目录。

-l,--list:列出所有可用模块。

-s,--snippet:只显示playbook说明的代码段。

-v:等同于--version,显示工具版本号。

接下来看些简单的实例:

(1.)显示所有可用的模块

执行命令:

ansible-doc  -l

执行结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_redis key 单冒号 和双冒号_07

(2.)以yum模块为例,我们希望获取yum模块的HELP说明。

执行命令:

ansible-doc yum

执行结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_redis key 单冒号 和双冒号_08

其他模块HELP说明以此类推。下面通过Ansible内置模块来完成一些具体工作。

1.安装httpd服务并查看服务的版本号

(1.)安装httpd服务

执行命令:

ansible  apps  -m  yum   -a  'name=httpd state=present'

返回结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_ansible_09

其中:

changed:主机是否有变更,True为有;false为没有(第一次运行或事先没有安装,返回值一般是True,否则为false)。

msg:安装过程信息

rc:0,resultcode:结果返回码,非0返回码往往是红色并且错误的返回,非常明显。

(2.).查看服务版本号

执行命令:

ansible apps  -m  command   -a  '/usr/sbin/httpd -V'

返回结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_ansible_10

部分执行结果解释:

192.168.1.18:表示命令执行的对象

success:表示命令执行的返回状态为成功状态。

rc=0:表示命令执行的状态码为0

>>:该符号后返回的所有内容为执行/usr/sbin/httpd -V命令返回的信息。

2.为所有服务器安装ntp服务,并设置为开机自启动。

(1.)安装ntp服务

执行命令:

ansible  apps  -s  -m  yum  -a  "name=ntp state=present"

返回结果如下: 

redis key 单冒号 和双冒号 redis 冒号分隔符含义_awk_11

(2.)启动ntp服务,并设置为开机自启动。

执行命令:

ansible apps  -m  service  -a  "name=ntp state=started  enabled=yes"

执行结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_shell_12

返回的结果不再一一介绍了,相信已经懂了。

Ad-Hoc组管理和特定主机变更

Ad-Hoc组定义:Ad-Hoc的组功能定义在Inventory(清单)文件中,默认路径是/etc/ansible/hosts,书写格式遵循INI风格,中括号中的字符为组名。可以将同一个主机名称之后使用冒号加端口号来标明。

接下来即将使用Ansible搭建一套完整的架构应用去学习Ad-Hoc的组管理方式。

本次架构规划了前端Proxy、web Service和后面DB一套完整应用,下面便是架构拓扑图:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_git_13

如上图所示是简化后的互联网web服务架构, 用户请求通过proxy转发至后端WebServers响应,通过NoSQL服务缓冲后,最终将请求传送到DB这样的一个过程。

准备部署环境如下:

定义 Inventorycat(清单) /etc/ansible/hosts:  

[proxy]

192.168.1.18

[app]

192.168.1.27

192.168.1.29

[nosql]

192.168.1.30

[db]

192.168.1.19

应用分布如下:

[proxy]组:Nginx

[app]组:Nginx+PHP+Django

[nosql]组:Redis

[db]组:Mariadb

Ad-Hoc配置管理:配置Proxy与Web  Servers实践

接下来我们按Proxy、WebServers 依次顺序部署应用。

(1.)Ad-Hoc配置管理Proxy(即Nginx)

小提示:

首先配置好对方nginx的yum源让主机能够安装上nginx服务。

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1

利用ansible安装Nginx执行命令:

ansible proxy -m yum -a "name=nginx state=present"

安装结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_shell_14

部分执行结果解释:

changed:true,//表示本次命令对执行的目标有变更,True为第一次安装,如再执行一次则为false,表示执行的目标没有变更,这里的false和true不代表该命令执行成功或失败,只是表示执行目标是否被变更。

rc:0,//resultcode的简写,表示命令执行结果返回状态,非0均为异常,命令执行失败

results:[ //执行结果信息返回

安装完Nginx让我们来检查一下Nginx是否安装成功,可以执行如下命令:

ansible proxy -m  command -a "nginx -v"

如果安装成功则显示如下结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_git_15

如上所示是Nginx就安装好了,其实通过Ansible的YUM模块来安装Nginx有很多种方法,通过网络YUM源安装是其中的一种,

那么还可以从本地YUM源安装,以及通过去仓库拉去相关服务的源也是可以的。

 

(2.)Ad-Hoc配置管理Web Servers

安装完了Nginx前端代理服务,同时Web Servers需要部署Nginx 、PHP和Django,其中Nginx、PHP依然通过YUM模块实现,Django推荐使用PIP或easy_install方式。

小提示:因为断电原因后面的ip有所变化,不过一样好理解!!!

同样和之前安装的Nginx服务一样要把Nginx、PHP的YUM源配置上

Nginx、PHP安装命令如下:

ansible app -m yum  -a  "name=nginx  state=present"

ansible app -m yum  -a  "name=php  state=present"

显示Nginx安装执行结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_shell_16

显示PHP安装执行结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_git_17

Django命令安装如下:

(1.)安装MySQL-python和python-setuptools依赖包。

ansible  app  -m  yum  -a  "name=MySQL-python state=present"

ansible app  -m   yum  -a  "name=php  state=present"

安装MySQL-python显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_redis key 单冒号 和双冒号_18

安装python-setuptools显示如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_redis key 单冒号 和双冒号_19

(2.)安装Django:

ansible  app  -m  pip  -a  "name=django  state=present"

安装显示结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_awk_20

检查Django安装是否正常 ,执行命令如下:

ansible app -m command -a "python -c 'import django; print django.get_version()'"

显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_ansible_21

如果上述安装报错请检查python版本,其中Django依赖Python2.7+版本。

截止目前,proxy & webservers部署完毕了。

Ad-Hoc配置后端:配置NoSQL与Database Servers实践

接下来我们使用类似的方法配置NoSQL和DB服务。

Redis安装命令如下:

ansible nosql -m  yum -a "name=redis state=present"

显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_ansible_22

Redis安装完,进行检查看安装是否正常,执行命令如下:

ansible nosql -m command -a "redis-cli --version"

显示版本结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_awk_23

安装Mariadb,具体操作步骤如下:

(1.)添加yum源,vim编辑/etc/yum.repos.d/mariadb.repo添加如下内容:

[mariadb]
name = Mariadb
baseurl=http://yum.mariadb.org/10.1/centos/7.2/x86_64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

 (2.)安装MariaDB-server,执行如下命令:

ansible  db  -m  yum  -a  "name=MariaDB-server  state=present"

显示结果如下: 

redis key 单冒号 和双冒号 redis 冒号分隔符含义_git_24

(3.)安装MariaDB-client,执行命令如下:

ansible db  -m yum -a "name=MariaDB-client state=present"

显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_redis key 单冒号 和双冒号_25

截止目前,所有的应用成功部署完毕。

Ad-Hoc特定主机变更

前面我们通过搭建了一套主流web应用框架熟悉了Ansible的组管理,接下来为大家介绍如何针对特定服务器做为变更。

Ansible有多种方式实现针对特定主机做变更。

(1.)--limit:通过 --limit参数限定主机做变更。

在APP组启动192.168.1.19的NTP服务,执行下列命令查看启动后的NTP服务的状态:

ansible app -m command -a "systemctl status ntpd.service" --limit "192.168.1.19"

显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_ansible_26

(2.)指定IP:通过指定具体IP限定主机做变更。

启动192.168.1.19的NTP服务,执行下列命令查看启动后的NTP服务的状态:

ansible 192.168.1.19 -m command -a "systemctl status ntpd.service"

显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_awk_27

(3.)用 “:”做分隔符,指定多台机器做变更。

启动192.168.1.19和192.168.1.14的NTP服务,执行下列命令查看启动后的NTP服务的状态:

ansible "192.168.1.14:192.168.1.19" -m command -a "systemctl status ntpd.service"

显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_git_28

(4.)通过“*”泛匹配,更灵活地针对多台主机做变更。

启动192.168.1.*所有主机的NTP服务,执行下列命令查看启动后的NTP服务的状态:

ansible 192.168.1.* -m  command -a "systemctl status ntpd.service"

显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_ansible_29

到目前为止Ad-Hoc组管理 及特定主机变更我们已经掌握,这对灵活管理海量服务器有很大帮助。

关于组及指定主机管理介绍到此结束。接下来为大家介绍的是Ad-Hoc基于用户管理。

Ad-Hoc用户与组管理

ansible系统用户模块有如下两个:

Linux系统用户管理:user

windows系统用户管理:win_user

Linux用户管理:

User模块功能诸多,模块属性如下:

append  yes:增量添加group  no:全量变更group,只设置groups指定的group组。

comment: 可选设置用户账户的描述(又名GECOS)

createhome:默认选项yes,当创建用户期时或家目录不存在时 为用户创建HOME目录。

expires(1.9版本增加):1.9版本的新增功能,用户过期时间,不支持的平台该参数将被忽略,现在支持Linux和FreeBSD

force:强制,当和state=absent结合使用时,效果等同于userdel  --force

generate_ssh_key: 是否生成SSH key,不会覆盖已有的SSH key

group :(可选)设置用户属组

groups:设置用户附加群组,使用逗号分隔多个群组,如果参数为空(即‘groups=’),则删除用户所有附加组(属组不受影响)

home:(可选)设置用户家目录

login_class:(可选)设置FreeBSD、OPenBSD、NetBSD系统的用户登录class

move_home:如设置为yes,结合使用home=,临时迁移用户家目录到特定目录。

name:用户名

non_unique:(可选)和-u结合使用,允许改变用户ID为非唯一值。

password:(可选)设置用户密码为该项指定的密码(加密后的密码)

remove:结合state=absent使用相当于userdel --remove

seuser(2.1版本增加):(可选)设置seuser类型启用SELinux

shell :(可选)设置用户shell

skeleton:(可选)设置用户的skel目录,需和createhome参数结合使用。

ssh_key_bits:(可选)指定生成的SSH key加密位数。

ssh_key_comment:(默认值:ansible-generated on  $HOSTNAME)(可选)定义SSH key注释

ssh_key_file:(默认值.ssh/id_rsa)(可选)指定SSH key 文件名,如果该文件名是相对路径,则默认路径为用户家目录。

ssh_key_passphrase:设置SSH key密码,如果没有提供密码,则默认没有加密。

ssh_key_type:(可选)设置SSH Key 类型,具体可用的SSH key类型取决于目标主机

state:present Present:新建(使存在)用户,absent:删除用户

system:当创建新账户时,该选项为yes,为用户设置系统账户,该设置对已经存在的用户无效。

uid:(可选)设置用户UID

update_password(1.3版本增加):always:只有当密码不相同时才会更新密码,on_create:只为新用户设置密码。

接下来为大家介绍用户相关的五大场景应用,以供参考。

场景1:新增用户

需求描述:新增用户dba,使用BASH Shell,附加组为admins,dbagroup,家目录为/home/dba/。

该场景中我们可以掌握如下技能点:

 (1.)groups设定:groups=用户组1,用户组2......

 (2.)增量添加属组:append=yes

 (3.)表名属组状态为新建:state=present

执行如下命令:

ansible db -m user -a "name=dba shell=/bin/bash groups=admins,dbagroup append=yes home=/home/dba/ state=present"

返回结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_shell_30

场景2:修改用户属组

需求描述:修改DBA附件组为dbagroups(即删除admins组权限)。

该场景中我们可以掌握如下技能点。

全量变更属组信息:append=no

执行命令如下:

ansible db  -m user -a "name=dba  groups=dbagroup append=no"

返回结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_git_31

提示:删除admins组权限的命令中append值为no。另外,细心的朋友会发现,新增用户时,ansible默认为用户添加用户组(primary group)。

场景3:修改用户属性

需求描述:设置dba用户的过期时间为2016/6/1 18:00:00(UNIXTIME:1464775200)。

该场景中我们可以掌握如下技能点。

(1.)设置用户登录过期时间:expire=1464775200

(2.)UNIX时间转换:2016/6/1 18:00:00需转换为UNIXTIME格式(不做介绍,请自行百度)

执行如下命令:

ansible db -m user -a "name=dba expires=1464775200"

这样,我们已经完成了DBA用户的过期时间设置。

场景4:删除用户

需求描述:删除用户DBA,并删除其家目录和邮件列表。

该场景中我们可以掌握如下技能点:

(1.)表明属组状态为删除:state=absent

(2.)设定remove=yes:remove=yes

执行命令如下:

ansible db -m user -a "name=dba state=absent  remove=yes"

返回显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_awk_32

结果检查:到对应主机使用root用户查看/etc/passwd是否存在dba用户。或执行命令id dba确认是否有返回结果。

场景5:变更用户密码

需求描述:设置系统用户tom的密码为redhat123

执行命令如下:

ansible db -m user -a "name=tom shell=/bin/bash password=to46pW3GOukvA update_password=always"

显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_redis key 单冒号 和双冒号_33

注意:password后面的密码并非真正的密码。官网上介绍了两种密码加密方式。

方式1:使用命令mkpasswd生成密码

(1.)查找安装包名称

执行命令如下:

yum whatprovides */mkpasswd

执行结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_shell_34

(2.)安装软件包

执行命令如下:

yum  -y install  expect

显示结果如下:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_redis key 单冒号 和双冒号_35

(3.)使用mkpasswd生成密码。

执行如下命令:

mkpasswd --method=SHA-512

方式2:使用Python的passlib、getpass库生成密码。

(1.)安装passlib(Python版本建议2.7以上)

执行如下命令:

pip install passlib

执行显示结果:

redis key 单冒号 和双冒号 redis 冒号分隔符含义_awk_36

(2.)生成密码

python3.x系列版本请使用如下命令(sha512加密算法)。

python -c "from passlib.hash import sha512_crypt; import  getpass; print (sha512_crypt.encrypt(getpass.getpass()))"

python3.x系列版本请使用如下命令(普通加密算法)。

python -c 'import  crypt; print (crypt.crypt("redhat123","dba"))'

python2.x系列版本请使用如下命令(sha512加密算法)。

python -c "from passlib.hash  import sha512_crypt; import getpass ; print sha512_crypt.encrypt(getpass.getpass())"

python2.x系列版本请使用如下命令(普通加密算法)。

python -c  'import  crypt; print (crypt.crypt("redhat123","dba"))'

应用层用户管理

以MySQL用户管理为例。

新增MySQL用户stanley,设置登录密码为magedu@bj,对zabbix.*表有ALL权限。

执行如下命令:

ansible db  -m  mysql_user -a 'login_host=localhost login_password=magedu login_user=root name=stanley password=magedu@bj priv=zabbix.*:ALL state=present'

登录验证步骤如下:

(1.)在MySQL服务器上进行测试登录

MySQL  -u stanley -p  maedu@bj

(2.)执行如下命令,验证权限是否正确:

show  grants for  'stanley'@'localhost';