一、Ansible简介
1.ansible是什么?
ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
简单来说ansible是一种架构,本身没有批量部署的能力批量部署能力是由模块来提供的!而且不需要在被控制的主机上安装任何东西,因为ansible是通过ssh协议来与远程主机通讯的
2.ansible特点
- 部署简单,只需在主控端部署Ansible环境,被控端无需做任何操作;
- 默认使用SSH协议对设备进行管理;
- 有大量常规运维操作模块,可实现日常绝大部分操作;
- 配置简单、功能强大、扩展性强;
- 支持API及自定义模块,可通过Python轻松扩展;
- 通过Playbooks来定制强大的配置、状态管理;
- 轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
3.ansible架构
主要模块
- Ansible:ansible核心程序
- HostInventory:主机清单,记录由Ansible管理的主机信息,包括端口、密码、ip等。
- Playbooks:剧本,YAML格式文件,多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能。
- CoreModules:核心模块,主要操作是通过调用核心模块来完成管理任务。
- CustomModules:自定义模块,完成核心模块无法完成的功能,支持多种语言。
- ConnectionPlugins:连接插件,Ansible和Host通信使用
工作流程
- 用户使用ansible程序
- ansible查看主机清单(HostInventory)
- ansible知道要控制的都有谁了,开始调用模块、剧本或角色
- 通过连接模块连接远程主机,部署任务开始
命令执行过程
- 加载自己的配置文件,默认/etc/ansible/ansible.cfg;
- 查找对应的主机配置文件,找到要执行的主机或者组;
- 加载自己对应的模块文件,如 command;
- 通过ansible将模块或命令生成对应的临时py文件(python脚本), 并将该文件传输至远程服务器;
- 对应生成用户的家目录的.ansible/tmp/XXX/XXX.PY文件;
- 给文件 +x 执行权限;
- 执行并返回结果;
- 删除临时py文件,sleep 0退出;
二、Ansible 配置
1 安装ansible
2 目录结构
安装目录如下(yum安装):
配置文件目录:/etc/ansible/
执行文件目录:/usr/bin/
Lib库依赖目录:/usr/lib/pythonX.X/site-packages/ansible/
Help文档目录:/usr/share/doc/ansible-X.X.X/
Man文档目录:/usr/share/man/man1/
3 ansible配置文件
ansible 的配置文件为/etc/ansible/ansible.cfg,ansible 有许多参数,下面我们列出一些常见的参数:
inventory = /etc/ansible/hosts #这个参数表示资源清单inventory文件的位置
library = /usr/share/ansible #指向存放Ansible模块的目录,支持多个目录方式,只要用冒号(:)隔开就可以
forks = 5 #并发连接数,默认为5
sudo_user = root #设置默认执行命令的用户
remote_port = 22 #指定连接被管节点的管理端口,默认为22端口,建议修改,能够更加安全
host_key_checking = False #设置是否检查SSH主机的密钥,值为True/False。关闭后第一次连接不会提示配置实例
timeout = 60 #设置SSH连接的超时时间,单位为秒
log_path = /var/log/ansible.log #指定一个存储ansible日志的文件(默认不记录日志)
4 ansible主机清单
有多种定义方式:
1、 直接指明主机地址或主机名:
192.168.100.10
2、定义一个组名,把主机加进去,当然也可以用通配符来匹配!
[test]
192.168.100.[1:3]0
....
...
...
"/etc/ansible/hosts" 57L, 1169C 1,1
5 ansible颜色
Ansible执行的时候根据结果会显示为绿色(成功执行),黄色(成功伴随状态改变)和红色(执行失败)等颜色,颜色的显示与changed的状态相关联,并可以在ansible.cfg中进行定制颜色的设定。
三、Ansible 常用命令
1 ansible 命令集
/usr/bin/ansible Ansibe AD-Hoc 临时命令执行工具,常用于临时命令的执行
/usr/bin/ansible-doc Ansible 模块帮助文档
/usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块 的官网平台
/usr/bin/ansible-playbook Ansible 任务集编排工具
/usr/bin/ansible-pull Ansible远程执行命令的工具,拉取配置而非推送配置(使用较少,海量机器时使用,对运维的架构能力要求较高)
/usr/bin/ansible-vault Ansible 文件加密工具
/usr/bin/ansible-console Ansible基于Linux Consoble界面可与用户交互的命令执行工具
其中,我们比较常用的是/usr/bin/ansible和/usr/bin/ansible-playbook。
2 ansible-doc 命令
[root@ansible ~]# ansible-doc
Usage: ansible-doc [options] [module...]
Options:
-h, --help show this help message and exit # 显示命令参数API文档
-l, --list List available modules #列出可用的模块
-M MODULE_PATH, --module-path=MODULE_PATH #指定模块的路径
specify path(s) to module library (default=None)
-s, --snippet Show playbook snippet for specified module(s) #显示playbook制定模块的用法
-v, --verbose verbose mode (-vvv for more, -vvvv to enable # 显示ansible-doc的版本号查看模块列表:
connection debugging)
--version show program's version number and exit
例如:
[root@ansible ansible]# ansible-doc -l |grep nginx
nginx_status_info Retrieve information on nginx stat...
nginx_status_facts Retrieve nginx status facts
[root@ansible ansible]# ansible-doc -s nginx_status_info
- name: Retrieve information on nginx status.
nginx_status_info:
timeout: # HTTP connection timeout in seconds.
url: # (required) URL of the nginx status.
3 ansible 命令格式
命令的具体格式如下:
ansible host-pattern -m 模块名 -a ‘参数’
通过ansible -h查看
[root@ansible ansible]# ansible -h
-a MODULE_ARGS #模块的参数,如果执行默认COMMAND的模块,即是命令参数,如: “date”,“pwd”等等
-k,--ask-pass #ask for SSH password。登录密码,提示输入SSH密码而不是假设基于密钥的验证
--ask-su-pass #ask for su password。su切换密码
-K,--ask-sudo-pass #ask for sudo password。提示密码使用sudo,sudo表示提权操作
--ask-vault-pass #ask for vault password。假设我们设定了加密的密码,则用该选项进行访问
-B SECONDS #后台运行超时时间
-C #模拟运行环境并进行预运行,可以进行查错测试
-c CONNECTION #连接类型使用
-f FORKS #并行任务数,默认为5
-i INVENTORY #指定主机清单的路径,默认为/etc/ansible/hosts
--list-hosts #查看有哪些主机组
-m MODULE_NAME #执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数
-o #压缩输出,尝试将所有结果在一行输出,一般针对收集工具使用
-S #用 su 命令
-R SU_USER #指定 su 的用户,默认为 root 用户
-s #用 sudo 命令
-U SUDO_USER #指定 sudo 到哪个用户,默认为 root 用户
-T TIMEOUT #指定 ssh 默认超时时间,默认为10s,也可在配置文件中修改
-u REMOTE_USER #远程用户,默认为 root 用户
-v #查看详细信息,同时支持-vvv,-vvvv可查看更详细信息
4 ssh免密登录
原理
实验
#1.生成私钥
[root@ansible ~]# ssh-keygen
#2.向主机分发私钥
[root@ansible ~]# ssh-copy-id root@192.168.100.10
[root@ansible ~]# ssh-copy-id root@192.168.100.20
四、Ansible 常用模块
1 ping模块
[root@ansible ~]# ansible 192.168.100.10 -m ping
192.168.100.10 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
这样就说明我们的主机是连通状态的。接下来的操作才可以正常进行。
2 shell模块
shell模块很常用,它可以在远程主机上调用shell解释器运行命令
[root@ansible ~]# head -10 /etc/ansible/hosts
[test]
192.168.100.[1:3]0
[wsr]
192.168.100.10 http_port=81
192.168.100.20 http_port=82
[wsr:vars]
nodename=mail
domainname=edu
[root@ansible ~]# ansible wsr -m shell -a 'ls -l'
192.168.100.10 | CHANGED | rc=0 >>
total 188
drwxr-xr-x. 2 root root 6 Aug 11 2020 a
-rw-------. 1 root root 1260 Jun 3 2020 anaconda-ks.cfg
-rw-r--r--. 1 root root 0 Aug 11 2020 b
-rw-r--r-- 1 root root 13 Jun 21 04:09 f4
-rw-r--r-- 1 root root 6540 Jun 21 04:22 log.tar.xz
lrwxrwxrwx. 1 root root 17 Jun 20 22:30 selinux -> ../selinux/config
drwxr-xr-x. 2 root root 25 Jun 20 22:08 sh
-rw-r--r-- 1 root root 175412 Jun 22 03:53 vsftpd-3.0.2-25.el7.x86_64.rpm
192.168.100.20 | CHANGED | rc=0 >>
total 188
drwxr-xr-x. 2 root root 6 Aug 11 2020 a
-rw-------. 1 root root 1260 Jun 3 2020 anaconda-ks.cfg
-rw-r--r--. 1 root root 0 Aug 11 2020 b
-rw-r--r-- 1 root root 13 Jun 21 04:09 f4
-rw-r--r-- 1 root root 6516 Jun 21 04:22 log.tar.xz
-rw-r--r-- 1 root root 175412 Jun 22 03:53 vsftpd-3.0.2-25.el7.x86_64.rpm
# 总结
<font color=#999AAA >提示:
3 command模块
这个模块可以直接在远程主机上执行命令,并将结果返回本主机。
命令模块接受命令名称,后面是空格分隔的列表参数。给定的命令将在所有选定的节点上执行。它不会通过shell进行处理,比如$HOME和操作如"<",">","|",";","&"工作(需要使用(shell)模块实现这些功能)。
下面来看一看该模块下常用的几个命令:
- chdir # 在执行命令之前,先切换到该目录 executable # 切换shell来执行命令,需要使用命令的绝对路径
- free_form # 要执行的Linux指令,一般使用Ansible的-a参数代替。
- creates # 一个文件名,当这个文件存在,则该命令不执行,可以
用来做判断 - removes # 一个文件名,这个文件不存在,则该命令不执行
[root@ansible ~]# ansible wsr -m command -a 'chdir=/data ls'
192.168.100.20 | CHANGED | rc=0 >>
file1
file2
file3
for1.conf
for2.conf
for3.conf
httpd.conf
192.168.100.10 | CHANGED | rc=0 >>
file1
file2
file3
for1.conf
for2.conf
for3.conf
httpd.conf
4 copy模块
这个模块用于将文件复制到远程主机,同时支持给定内容生成文件和修改权限等。
其相关选项如下:
- src #被复制到远程主机的本地文件。可以是绝对路径,也可以是相对路径。如果路径是一个目录,则会递归复制,用法类似于"rsync"
- content #用于替换"src",可以直接指定文件的值
- dest #必选项,将源文件复制到的远程主机的绝对路径
- backup #当文件内容发生改变后,在覆盖之前把源文件备份,备份文件包含时间信息
- directory_mode #递归设定目录的权限,默认为系统默认权限
- force #当目标主机包含该文件,但内容不同时,设为"yes",表示强制覆盖;设为"no",表示目标主机的目标位置不存在该文件才复制。默认为"yes"
- others #所有的 file 模块中的选项可以在这里使用
其中src,dest,backup,mode用的较多
复制
[root@ansible ~]# touch 2021710
[root@ansible ~]# ansible wsr -m copy -a 'src=2021710 dest=/data/2021710'
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
"dest": "/data/2021710",
"gid": 0,
"group": "root",
"md5sum": "d41d8cd98f00b204e9800998ecf8427e",
"mode": "0644",
"owner": "root",
"size": 0,
"src": "/root/.ansible/tmp/ansible-tmp-1625931089.28-8051-80193366038951/source",
"state": "file",
"uid": 0
}
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
"dest": "/data/2021710",
"gid": 0,
"group": "root",
"md5sum": "d41d8cd98f00b204e9800998ecf8427e",
"mode": "0644",
"owner": "root",
"size": 0,
"src": "/root/.ansible/tmp/ansible-tmp-1625931089.28-8052-82580429716175/source",
"state": "file",
"uid": 0
}
权限和备份
[root@ansible ~]# ansible wsr -m copy -a 'content="i am bad boy\n" backup=yes dest=/data/2021710 mode=666'
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"backup_file": "/data/2021710.11493.2021-07-10@11:32:39~",
"changed": true,
"checksum": "444281122cde3d31fa394ffe2d29d9a1fa2411f3",
"dest": "/data/2021710",
"gid": 0,
"group": "root",
"md5sum": "e2ea0ae0489f588fd0e7adcdc361ff70",
"mode": "0666",
"owner": "root",
"size": 13,
"src": "/root/.ansible/tmp/ansible-tmp-1625931158.27-8105-89064400502466/source",
"state": "file",
"uid": 0
}
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"backup_file": "/data/2021710.11427.2021-07-10@11:32:39~",
"changed": true,
"checksum": "444281122cde3d31fa394ffe2d29d9a1fa2411f3",
"dest": "/data/2021710",
"gid": 0,
"group": "root",
"md5sum": "e2ea0ae0489f588fd0e7adcdc361ff70",
"mode": "0666",
"owner": "root",
"size": 13,
"src": "/root/.ansible/tmp/ansible-tmp-1625931158.28-8106-201363635505942/source",
"state": "file",
"uid": 0
}
检测
其中一大串名字的就是备份后的名字,也可以看到权限为666
[root@ansible ~]# ansible wsr -m shell -a 'ls -l /data'
192.168.100.10 | CHANGED | rc=0 >>
total 32
-rw-rw-rw- 1 root root 13 Jul 10 11:32 2021710
-rw-r--r-- 1 root root 0 Jul 10 11:31 2021710.11493.2021-07-10@11:32:39~
-rw-rw-rw- 1 root root 21 Jul 10 11:20 a.sh
-rw-r--r-- 1 root root 0 Jul 3 23:14 file1
-rw-r--r-- 1 root root 0 Jul 3 23:14 file2
-rw-r--r-- 1 root root 0 Jul 3 23:14 file3
-rw-r--r-- 1 root root 63 Jul 4 11:51 for1.conf
-rw-r--r-- 1 root root 267 Jul 4 12:06 for2.conf
-rw-r--r-- 1 root root 171 Jul 5 04:05 for3.conf
-rw-r--r-- 1 apache root 11753 Jul 10 03:21 httpd.conf
192.168.100.20 | CHANGED | rc=0 >>
total 32
-rw-rw-rw- 1 root root 13 Jul 10 11:32 2021710
-rw-r--r-- 1 root root 0 Jul 10 11:31 2021710.11427.2021-07-10@11:32:39~
-rw-rw-rw- 1 root root 21 Jul 10 11:20 a.sh
-rw-r--r-- 1 root root 0 Jul 3 23:14 file1
-rw-r--r-- 1 root root 0 Jul 3 23:14 file2
-rw-r--r-- 1 root root 0 Jul 3 23:14 file3
-rw-r--r-- 1 root root 63 Jul 4 11:51 for1.conf
-rw-r--r-- 1 root root 267 Jul 4 12:06 for2.conf
-rw-r--r-- 1 root root 171 Jul 5 04:05 for3.conf
-rw-r--r-- 1 apache root 11753 Jul 10 03:21 httpd.conf
5 yum模块
通过yum装包
其选项如下:
- name= #所安装的包的名称
- state= #present—>安装, latest—>安装最新的, absent—> 卸载软件。
- 其余不常用的就不列举了
安装
state默认为present
[root@ansible ~]# ansible wsr -m yum -a 'name=vim'
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"installed": [
"vim"
]
},
"msg": "Repository base is listed more than once in the configuration\nRepository updates is listed more than once in the configuration\nRepository extras is listed more than once in the configuration\nRepository centosplus is listed more than once in the configuration\nRepository epel is listed more than once in the configuration\nRepository epel-debuginfo is listed more than once in the configuration\nRepository epel-source is listed more than once in the configuration\n",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package vim-enhanced.x86_64 2:7.4.629-8.el7_9 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n vim-enhanced x86_64 2:7.4.629-8.el7_9 updates 1.1 M\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 1.1 M\nInstalled size: 2.2 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : 2:vim-enhanced-7.4.629-8.el7_9.x86_64 1/1 \n Verifying : 2:vim-enhanced-7.4.629-8.el7_9.x86_64 1/1 \n\nInstalled:\n vim-enhanced.x86_64 2:7.4.629-8.el7_9 \n\nComplete!\n"
]
}
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"installed": [
"vim"
]
},
"msg": "Repository base is listed more than once in the configuration\nRepository updates is listed more than once in the configuration\nRepository extras is listed more than once in the configuration\nRepository centosplus is listed more than once in the configuration\nRepository epel is listed more than once in the configuration\nRepository epel-debuginfo is listed more than once in the configuration\nRepository epel-source is listed more than once in the configuration\n",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package vim-enhanced.x86_64 2:7.4.629-8.el7_9 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n vim-enhanced x86_64 2:7.4.629-8.el7_9 updates 1.1 M\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 1.1 M\nInstalled size: 2.2 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : 2:vim-enhanced-7.4.629-8.el7_9.x86_64 1/1 \n Verifying : 2:vim-enhanced-7.4.629-8.el7_9.x86_64 1/1 \n\nInstalled:\n vim-enhanced.x86_64 2:7.4.629-8.el7_9 \n\nComplete!\n"
]
}
卸载
改变state的状态为absent即可
[root@ansible ~]# ansible wsr -m yum -a 'name=vim state=absent'
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"removed": [
"vim"
]
},
"msg": "Repository base is listed more than once in the configuration\nRepository updates is listed more than once in the configuration\nRepository extras is listed more than once in the configuration\nRepository centosplus is listed more than once in the configuration\nRepository epel is listed more than once in the configuration\nRepository epel-debuginfo is listed more than once in the configuration\nRepository epel-source is listed more than once in the configuration\n",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror\nResolving Dependencies\n--> Running transaction check\n---> Package vim-enhanced.x86_64 2:7.4.629-8.el7_9 will be erased\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nRemoving:\n vim-enhanced x86_64 2:7.4.629-8.el7_9 @updates 2.2 M\n\nTransaction Summary\n================================================================================\nRemove 1 Package\n\nInstalled size: 2.2 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Erasing : 2:vim-enhanced-7.4.629-8.el7_9.x86_64 1/1 \n Verifying : 2:vim-enhanced-7.4.629-8.el7_9.x86_64 1/1 \n\nRemoved:\n vim-enhanced.x86_64 2:7.4.629-8.el7_9 \n\nComplete!\n"
]
}
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"changes": {
"removed": [
"vim"
]
},
"msg": "Repository base is listed more than once in the configuration\nRepository updates is listed more than once in the configuration\nRepository extras is listed more than once in the configuration\nRepository centosplus is listed more than once in the configuration\nRepository epel is listed more than once in the configuration\nRepository epel-debuginfo is listed more than once in the configuration\nRepository epel-source is listed more than once in the configuration\n",
"rc": 0,
"results": [
"Loaded plugins: fastestmirror\nResolving Dependencies\n--> Running transaction check\n---> Package vim-enhanced.x86_64 2:7.4.629-8.el7_9 will be erased\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nRemoving:\n vim-enhanced x86_64 2:7.4.629-8.el7_9 @updates 2.2 M\n\nTransaction Summary\n================================================================================\nRemove 1 Package\n\nInstalled size: 2.2 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Erasing : 2:vim-enhanced-7.4.629-8.el7_9.x86_64 1/1 \n Verifying : 2:vim-enhanced-7.4.629-8.el7_9.x86_64 1/1 \n\nRemoved:\n vim-enhanced.x86_64 2:7.4.629-8.el7_9 \n\nComplete!\n"
]
}
6 file模块
该模块主要用于设置文件的属性,比如创建文件、创建链接文件、删除文件等。
下面是一些常见的命令:
force #需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group #定义文件/目录的属组。后面可以加上mode:定义文件/目录的权限
owner #定义文件/目录的属主。后面必须跟上path:定义文件/目录的路径
recurse #递归设置文件的属性,只对目录有效,后面跟上src:被链接的源文件路径,只应用于state=link的情况
dest #被链接到的路径,只应用于state=link的情况
state #状态,有以下选项:
directory:如果目录不存在,就创建目录
file:即使文件不存在,也不会被创建
link:创建软链接
hard:创建硬链接
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent:删除目录、文件或者取消链接文件
创建文件夹
[root@ansible ~]# ansible wsr -m file -a 'path=/data/2339 state=directory'
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/data/2339",
"size": 6,
"state": "directory",
"uid": 0
}
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/data/2339",
"size": 6,
"state": "directory",
"uid": 0
}
创建链接文件
[root@ansible ~]# ansible wsr -m file -a 'path=/data/2340 src=2339 state=link'
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/data/2340",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"size": 4,
"src": "2339",
"state": "link",
"uid": 0
}
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/data/2340",
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"size": 4,
"src": "2339",
"state": "link",
"uid": 0
}
测试
[root@ansible ~]# ansible wsr -a 'ls -l /data'
192.168.100.20 | CHANGED | rc=0 >>
total 32
-rw-rw-rw- 1 root root 13 Jul 10 11:32 2021710
-rw-r--r-- 1 root root 0 Jul 10 11:31 2021710.11427.2021-07-10@11:32:39~
drwxr-xr-x 2 root root 6 Jul 10 11:40 2339
lrwxrwxrwx 1 root root 4 Jul 10 11:42 2340 -> 2339
-rw-rw-rw- 1 root root 21 Jul 10 11:20 a.sh
-rw-r--r-- 1 root root 0 Jul 3 23:14 file1
-rw-r--r-- 1 root root 0 Jul 3 23:14 file2
-rw-r--r-- 1 root root 0 Jul 3 23:14 file3
-rw-r--r-- 1 root root 63 Jul 4 11:51 for1.conf
-rw-r--r-- 1 root root 267 Jul 4 12:06 for2.conf
-rw-r--r-- 1 root root 171 Jul 5 04:05 for3.conf
-rw-r--r-- 1 apache root 11753 Jul 10 03:21 httpd.conf
192.168.100.10 | CHANGED | rc=0 >>
total 32
-rw-rw-rw- 1 root root 13 Jul 10 11:32 2021710
-rw-r--r-- 1 root root 0 Jul 10 11:31 2021710.11493.2021-07-10@11:32:39~
drwxr-xr-x 2 root root 6 Jul 10 11:40 2339
lrwxrwxrwx 1 root root 4 Jul 10 11:42 2340 -> 2339
-rw-rw-rw- 1 root root 21 Jul 10 11:20 a.sh
-rw-r--r-- 1 root root 0 Jul 3 23:14 file1
-rw-r--r-- 1 root root 0 Jul 3 23:14 file2
-rw-r--r-- 1 root root 0 Jul 3 23:14 file3
-rw-r--r-- 1 root root 63 Jul 4 11:51 for1.conf
-rw-r--r-- 1 root root 267 Jul 4 12:06 for2.conf
-rw-r--r-- 1 root root 171 Jul 5 04:05 for3.conf
-rw-r--r-- 1 apache root 11753 Jul 10 03:21 httpd.conf
删除文件
只需把state改为absent即可
[root@ansible ~]# ansible wsr -m file -a ‘path=/data/2339 state=absent’
7 cron模块
该模块适用于管理cron计划任务的。
其使用的语法跟我们的crontab文件中的语法一致
- day= #日应该运行的工作( 1-31, *, */2, )
- hour= # 小时 ( 0-23, *, */2, )
- minute= #分钟( 0-59, *, */2, )
- month= # 月( 1-12, *, /2, )
- weekday= # 周 ( 0-6 for Sunday-Saturday, )
- job= #指明运行的命令是什么
- name= #定时任务描述
- reboot # 任务在重启时运行,不建议使用,建议使用special_time
- special_time
#特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时) - state #指定状态,present表示添加定时任务,也是默认设置,absent表示删除定时任务
- user # 以哪个用户的身份执行
[root@ansible ~]# ansible wsr -m cron -a 'name="echo words" minute=*/5 job="echo hello world"'
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"warningcron",
"None",
"echo words"
]
}
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"envs": [],
"jobs": [
"warningcron",
"None",
"echo words"
]
}
测试结果
[root@ansible ~]# ansible wsr -a 'crontab -l'
192.168.100.10 | CHANGED | rc=0 >>
#Ansible: warningcron
#* * * * 1,3,5 /usr/bin/wall FBI warning
#Ansible: None
#* * * * * /usr/bin/wall FBI warning
#Ansible: echo words
*/5 * * * * echo hello world
192.168.100.20 | CHANGED | rc=0 >>
#Ansible: warningcron
#* * * * 1,3,5 /usr/bin/wall FBI warning
#Ansible: None
#* * * * * /usr/bin/wall FBI warning
#Ansible: echo words
*/5 * * * * echo hello world
mission completely!!!
8 user模块
该模块主要是用来管理账户的
- comment # 用户的描述信息
- createhome # 是否创建家目录
- force # 在使用state=absent时, 行为与userdel –force一致.
- group # 指定基本组
- groups # 指定附加组,如果指定为(groups=)表示删除所有组
- home # 指定用户家目录
- move_home # 如果设置为home=时, 试图将用户主目录移动到指定的目录
- name # 指定用户名
- non_unique # 该选项允许改变非唯一的用户ID值
- password # 指定用户密码
- remove # 在使用state=absent时, 行为是与userdel –remove一致
- shell # 指定默认shell
- state # 设置帐号状态,不指定为创建,指定值为absent表示删除
- system # 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户
- uid # 指定用户的uid
添加一个用户并指定 uid
[root@ansible ~]# ansible wsr -m user -a 'name=zs uid=66666'
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1005,
"home": "/home/zs",
"name": "zs",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 66666
}
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"comment": "",
"create_home": true,
"group": 1005,
"home": "/home/zs",
"name": "zs",
"shell": "/bin/bash",
"state": "present",
"system": false,
"uid": 66666
}
[root@ansible ~]# ansible wsr -m shell -a 'getent passwd|grep zs'
192.168.100.10 | CHANGED | rc=0 >>
zs:x:66666:1005::/home/zs:/bin/bash
192.168.100.20 | CHANGED | rc=0 >>
zs:x:66666:1005::/home/zs:/bin/bash
删除用户
指定状态为absent即可
[root@ansible ~]# ansible wsr -m user -a 'name=zs uid=66666 state=absent'
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"force": false,
"name": "zs",
"remove": false,
"state": "absent"
}
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"force": false,
"name": "zs",
"remove": false,
"state": "absent"
}
[root@ansible ~]# ansible wsr -m shell -a 'getent passwd|grep zs'
192.168.100.10 | FAILED | rc=1 >>
non-zero return code
192.168.100.20 | FAILED | rc=1 >>
non-zero return code
9 group模块
该模块主要用于添加或删除组。
常用的选项如下:
- gid= #设置组的GID号
- name= #指定组的名称
- state= #指定组的状态,默认为创建,设置值为absent为删除
- system= #设置值为yes,表示创建为系统组
建立组并指定gid
[root@ansible ~]# ansible wsr -m group -a 'name=ls gid=888888'
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 888888,
"name": "ls",
"state": "present",
"system": false
}
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 888888,
"name": "ls",
"state": "present",
"system": false
}
[root@ansible ~]# ansible wsr -m shell -a 'cat /etc/group |grep 888888'
192.168.100.10 | CHANGED | rc=0 >>
ls:x:888888:
192.168.100.20 | CHANGED | rc=0 >>
ls:x:888888:
删除组
指定state为absent即可删除
[root@ansible ~]# ansible wsr -m group -a 'name=ls state=absent'
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "ls",
"state": "absent"
}
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "ls",
"state": "absent"
}
10 script模块
该模块用于将本机的脚本在被管理端的机器上运行。
[root@ansible tmp]# cat df.sh
#!/bin/bash
date >> /tmp/disk_total.log
df -lh >> /tmp/disk_total.log
[root@ansible tmp]# ansible wsr -m script -a '/tmp/df.sh'
192.168.100.10 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.100.10 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.100.10 closed."
],
"stdout": "",
"stdout_lines": []
}
192.168.100.20 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.100.20 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.100.20 closed."
],
"stdout": "",
"stdout_lines": []
}
测试
[root@ansible tmp]# ansible wsr -a 'cat /tmp/disk_total.log'
192.168.100.10 | CHANGED | rc=0 >>
Sat Jul 10 21:24:51 EDT 2021
Filesystem Size Used Avail Use% Mounted on
devtmpfs 475M 0 475M 0% /dev
tmpfs 487M 0 487M 0% /dev/shm
tmpfs 487M 7.6M 479M 2% /run
tmpfs 487M 0 487M 0% /sys/fs/cgroup
/dev/mapper/centos-root 8.0G 1.5G 6.6G 18% /
/dev/sr0 4.4G 4.4G 0 100% /mnt/centos
/dev/sda1 1014M 136M 879M 14% /boot
tmpfs 98M 0 98M 0% /run/user/0
192.168.100.20 | CHANGED | rc=0 >>
Sat Jul 10 21:24:51 EDT 2021
Filesystem Size Used Avail Use% Mounted on
devtmpfs 475M 0 475M 0% /dev
tmpfs 487M 0 487M 0% /dev/shm
tmpfs 487M 7.6M 479M 2% /run
tmpfs 487M 0 487M 0% /sys/fs/cgroup
/dev/mapper/centos-root 8.0G 1.5G 6.6G 18% /
/dev/sr0 4.4G 4.4G 0 100% /mnt/centos
/dev/sda1 1014M 136M 879M 14% /boot
tmpfs 98M 0 98M 0% /run/user/0
11 setup模块
通过调用facts(facts就是变量,内建变量)组件来收集主机信息,如vcpu个数,内存大小等…
可以使用filter来查看指定信息,调用后返回很多对应主机的信息,在后面的操作中可以根据不同的信息来做不同的操作
如redhat系列用yum安装,而debian系列用apt来安装软件。
[root@ansible tmp]# ansible wsr -m setup -a 'filter=*cpu*'
192.168.100.20 | SUCCESS => {
"ansible_facts": {
"ansible_processor_vcpus": 2,
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
192.168.100.10 | SUCCESS => {
"ansible_facts": {
"ansible_processor_vcpus": 2,
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}
12 service 模块
该模块用于服务程序的管理。
其主要选项如下:
- arguments #命令行提供额外的参数
- enabled #设置开机启动。
- name= #服务名称
- runlevel #开机启动的级别,一般不用指定。
- sleep #在重启服务的过程中,是否等待。如在服务关闭以后等待2秒再启动。(定义在剧本中。)
- state #有四种状态,分别为:started—>启动服务, stopped—>停止服务,
- restarted—>重启服务, reloaded—>重载配置
[root@ansible tmp]# ansible wsr -m service -a 'name=httpd state=restarted enabled=true'
192.168.100.20 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"enabled": true,
"name": "httpd",
"state": "started",
"status": {
"ActiveEnterTimestampMonotonic": "0",
"ActiveExitTimestampMonotonic": "0",
"ActiveState": "inactive",
"After": "basic.target remote-fs.target system.slice systemd-journald.socket network.target tmp.mount nss-lookup.target -.mount",
"AllowIsolate": "no",
"AmbientCapabilities": "0",
"AssertResult": "no",
"AssertTimestampMonotonic": "0",
"Before": "shutdown.target",
"BlockIOAccounting": "no",
"BlockIOWeight": "18446744073709551615",
"CPUAccounting": "no",
"CPUQuotaPerSecUSec": "infinity",
"CPUSchedulingPolicy": "0",
"CPUSchedulingPriority": "0",
"CPUSchedulingResetOnFork": "no",
"CPUShares": "18446744073709551615",
"CanIsolate": "no",
"CanReload": "yes",
"CanStart": "yes",
"CanStop": "yes",
"CapabilityBoundingSet": "18446744073709551615",
"ConditionResult": "no",
"ConditionTimestampMonotonic": "0",
"Conflicts": "shutdown.target",
"ControlPID": "0",
"DefaultDependencies": "yes",
"Delegate": "no",
"Description": "The Apache HTTP Server",
"DevicePolicy": "auto",
"Documentation": "man:httpd(8) man:apachectl(8)",
"EnvironmentFile": "/etc/sysconfig/httpd (ignore_errors=no)",
"ExecMainCode": "0",
"ExecMainExitTimestampMonotonic": "0",
"ExecMainPID": "0",
"ExecMainStartTimestampMonotonic": "0",
"ExecMainStatus": "0",
"ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"FailureAction": "none",
"FileDescriptorStoreMax": "0",
"FragmentPath": "/usr/lib/systemd/system/httpd.service",
"GuessMainPID": "yes",
"IOScheduling": "0",
"Id": "httpd.service",
"IgnoreOnIsolate": "no",
"IgnoreOnSnapshot": "no",
"IgnoreSIGPIPE": "yes",
"InactiveEnterTimestampMonotonic": "0",
"InactiveExitTimestampMonotonic": "0",
"JobTimeoutAction": "none",
"JobTimeoutUSec": "0",
"KillMode": "control-group",
"KillSignal": "18",
"LimitAS": "18446744073709551615",
"LimitCORE": "18446744073709551615",
"LimitCPU": "18446744073709551615",
"LimitDATA": "18446744073709551615",
"LimitFSIZE": "18446744073709551615",
"LimitLOCKS": "18446744073709551615",
"LimitMEMLOCK": "65536",
"LimitMSGQUEUE": "819200",
"LimitNICE": "0",
"LimitNOFILE": "4096",
"LimitNPROC": "3795",
"LimitRSS": "18446744073709551615",
"LimitRTPRIO": "0",
"LimitRTTIME": "18446744073709551615",
"LimitSIGPENDING": "3795",
"LimitSTACK": "18446744073709551615",
"LoadState": "loaded",
"MainPID": "0",
"MemoryAccounting": "no",
"MemoryCurrent": "18446744073709551615",
"MemoryLimit": "18446744073709551615",
"MountFlags": "0",
"Names": "httpd.service",
"NeedDaemonReload": "no",
"Nice": "0",
"NoNewPrivileges": "no",
"NonBlocking": "no",
"NotifyAccess": "main",
"OOMScoreAdjust": "0",
"OnFailureJobMode": "replace",
"PermissionsStartOnly": "no",
"PrivateDevices": "no",
"PrivateNetwork": "no",
"PrivateTmp": "yes",
"ProtectHome": "no",
"ProtectSystem": "no",
"RefuseManualStart": "no",
"RefuseManualStop": "no",
"RemainAfterExit": "no",
"Requires": "-.mount basic.target",
"RequiresMountsFor": "/var/tmp",
"Restart": "no",
"RestartUSec": "100ms",
"Result": "success",
"RootDirectoryStartOnly": "no",
"RuntimeDirectoryMode": "0755",
"SameProcessGroup": "no",
"SecureBits": "0",
"SendSIGHUP": "no",
"SendSIGKILL": "yes",
"Slice": "system.slice",
"StandardError": "inherit",
"StandardInput": "null",
"StandardOutput": "journal",
"StartLimitAction": "none",
"StartLimitBurst": "5",
"StartLimitInterval": "10000000",
"StartupBlockIOWeight": "18446744073709551615",
"StartupCPUShares": "18446744073709551615",
"StatusErrno": "0",
"StopWhenUnneeded": "no",
"SubState": "dead",
"SyslogLevelPrefix": "yes",
"SyslogPriority": "30",
"SystemCallErrorNumber": "0",
"TTYReset": "no",
"TTYVHangup": "no",
"TTYVTDisallocate": "no",
"TasksAccounting": "no",
"TasksCurrent": "18446744073709551615",
"TasksMax": "18446744073709551615",
"TimeoutStartUSec": "1min 30s",
"TimeoutStopUSec": "1min 30s",
"TimerSlackNSec": "50000",
"Transient": "no",
"Type": "notify",
"UMask": "0022",
"UnitFilePreset": "disabled",
"UnitFileState": "disabled",
"Wants": "system.slice",
"WatchdogTimestampMonotonic": "0",
"WatchdogUSec": "0"
}
}
192.168.100.10 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"enabled": true,
"name": "httpd",
"state": "started",
"status": {
"ActiveEnterTimestampMonotonic": "0",
"ActiveExitTimestampMonotonic": "0",
"ActiveState": "inactive",
"After": "remote-fs.target nss-lookup.target tmp.mount basic.target -.mount systemd-journald.socket system.slice network.target",
"AllowIsolate": "no",
"AmbientCapabilities": "0",
"AssertResult": "no",
"AssertTimestampMonotonic": "0",
"Before": "shutdown.target",
"BlockIOAccounting": "no",
"BlockIOWeight": "18446744073709551615",
"CPUAccounting": "no",
"CPUQuotaPerSecUSec": "infinity",
"CPUSchedulingPolicy": "0",
"CPUSchedulingPriority": "0",
"CPUSchedulingResetOnFork": "no",
"CPUShares": "18446744073709551615",
"CanIsolate": "no",
"CanReload": "yes",
"CanStart": "yes",
"CanStop": "yes",
"CapabilityBoundingSet": "18446744073709551615",
"ConditionResult": "no",
"ConditionTimestampMonotonic": "0",
"Conflicts": "shutdown.target",
"ControlPID": "0",
"DefaultDependencies": "yes",
"Delegate": "no",
"Description": "The Apache HTTP Server",
"DevicePolicy": "auto",
"Documentation": "man:httpd(8) man:apachectl(8)",
"EnvironmentFile": "/etc/sysconfig/httpd (ignore_errors=no)",
"ExecMainCode": "0",
"ExecMainExitTimestampMonotonic": "0",
"ExecMainPID": "0",
"ExecMainStartTimestampMonotonic": "0",
"ExecMainStatus": "0",
"ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }",
"FailureAction": "none",
"FileDescriptorStoreMax": "0",
"FragmentPath": "/usr/lib/systemd/system/httpd.service",
"GuessMainPID": "yes",
"IOScheduling": "0",
"Id": "httpd.service",
"IgnoreOnIsolate": "no",
"IgnoreOnSnapshot": "no",
"IgnoreSIGPIPE": "yes",
"InactiveEnterTimestampMonotonic": "0",
"InactiveExitTimestampMonotonic": "0",
"JobTimeoutAction": "none",
"JobTimeoutUSec": "0",
"KillMode": "control-group",
"KillSignal": "18",
"LimitAS": "18446744073709551615",
"LimitCORE": "18446744073709551615",
"LimitCPU": "18446744073709551615",
"LimitDATA": "18446744073709551615",
"LimitFSIZE": "18446744073709551615",
"LimitLOCKS": "18446744073709551615",
"LimitMEMLOCK": "65536",
"LimitMSGQUEUE": "819200",
"LimitNICE": "0",
"LimitNOFILE": "4096",
"LimitNPROC": "3795",
"LimitRSS": "18446744073709551615",
"LimitRTPRIO": "0",
"LimitRTTIME": "18446744073709551615",
"LimitSIGPENDING": "3795",
"LimitSTACK": "18446744073709551615",
"LoadState": "loaded",
"MainPID": "0",
"MemoryAccounting": "no",
"MemoryCurrent": "18446744073709551615",
"MemoryLimit": "18446744073709551615",
"MountFlags": "0",
"Names": "httpd.service",
"NeedDaemonReload": "no",
"Nice": "0",
"NoNewPrivileges": "no",
"NonBlocking": "no",
"NotifyAccess": "main",
"OOMScoreAdjust": "0",
"OnFailureJobMode": "replace",
"PermissionsStartOnly": "no",
"PrivateDevices": "no",
"PrivateNetwork": "no",
"PrivateTmp": "yes",
"ProtectHome": "no",
"ProtectSystem": "no",
"RefuseManualStart": "no",
"RefuseManualStop": "no",
"RemainAfterExit": "no",
"Requires": "basic.target -.mount",
"RequiresMountsFor": "/var/tmp",
"Restart": "no",
"RestartUSec": "100ms",
"Result": "success",
"RootDirectoryStartOnly": "no",
"RuntimeDirectoryMode": "0755",
"SameProcessGroup": "no",
"SecureBits": "0",
"SendSIGHUP": "no",
"SendSIGKILL": "yes",
"Slice": "system.slice",
"StandardError": "inherit",
"StandardInput": "null",
"StandardOutput": "journal",
"StartLimitAction": "none",
"StartLimitBurst": "5",
"StartLimitInterval": "10000000",
"StartupBlockIOWeight": "18446744073709551615",
"StartupCPUShares": "18446744073709551615",
"StatusErrno": "0",
"StopWhenUnneeded": "no",
"SubState": "dead",
"SyslogLevelPrefix": "yes",
"SyslogPriority": "30",
"SystemCallErrorNumber": "0",
"TTYReset": "no",
"TTYVHangup": "no",
"TTYVTDisallocate": "no",
"TasksAccounting": "no",
"TasksCurrent": "18446744073709551615",
"TasksMax": "18446744073709551615",
"TimeoutStartUSec": "1min 30s",
"TimeoutStopUSec": "1min 30s",
"TimerSlackNSec": "50000",
"Transient": "no",
"Type": "notify",
"UMask": "0022",
"UnitFilePreset": "disabled",
"UnitFileState": "disabled",
"Wants": "system.slice",
"WatchdogTimestampMonotonic": "0",
"WatchdogUSec": "0"
}
}