自定义 Ansible 在文件复制时的前缀
一开端 (yī
使用lineinfile模块时,我发现由于backup=yes参数生成的备份文件名不是很满意…
因此,我考虑了一些自由设置前缀且容易配置的方法。
构成
以下是对上述内容的中文本地化版本:
■控制节点(执行ansible命令的主机)
· CentOS 8.0.1905
· Ansible 2.9.2
■目标节点(由ansible进行配置管理的主机)
· CentOS 7.6.1810
请确认默认前缀。
首先,我会确认可以加入哪些前缀。
暂时先用Ansible创建备份文件的目标文件。
[ansible@controll ~]$ ansible host1 -m file -a "name=test.txt state=touch"
host1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "test.txt",
"gid": 1000,
"group": "ansible",
"mode": "0664",
"owner": "ansible",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 0,
"state": "file",
"uid": 1000
}
[ansible@target ~]$ ls
test.txt
确认默认前缀。
通过lineinfile模块指定backup=yes选项,随意进行编辑。
[ansible@controll ~]$ ansible host1 -m lineinfile -a "dest=test.txt line='foo' backup=yes"
host1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"backup": "test.txt.4031.2019-12-23@21:29:44~",
"changed": true,
"msg": "line added"
}
[ansible@target ~]$ ls
test.txt test.txt.4031.2019-12-23@21:29:44~
默认创建的前缀似乎是“原始文件名.pid(?)。YYYY-mm-dd@HH:MM:ss~”。但是,个人而言,我不喜欢使用@或:。
尝试为每个场景单独设置专属的前缀。
固定的前缀 (gù de zhui)
如果只是暂时需要备份,并且在工作完成后会删除备份文件的情况下,我认为使用copy模块是最方便的选择。
[ansible@controll ~]$ ansible host1 -m copy -a "src=test.txt dest=test.txt.bak remote_src=yes"
host1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
"dest": "./test.txt.bak",
"gid": 1000,
"group": "ansible",
"md5sum": "d41d8cd98f00b204e9800998ecf8427e",
"mode": "0664",
"owner": "ansible",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 0,
"src": "test.txt",
"state": "file",
"uid": 1000
}
[ansible@target ~]$ ls
test.txt test.txt.4031.2019-12-23@21:29:44~ test.txt.bak
成功创建了test.txt.bak。
需要注意的是要加上remote_user=yes。
由于src的目标默认指向控制节点,因此需要此参数将其指向目标节点。
將時刻作為前綴添加
大约在YYYYmmdd这样的情况下,在不需要使用”@”和”:”的情况下。
虽然我认为可能已经存在一个存储当前时间的变量,但在Ansible中似乎没有这样的功能。
因此,我决定在处理过程中执行date命令来获取时间。使用copy模块进行复制。
[ansible@controll ~]$ ansible host1 -m copy -a "src=test.txt remote_src=yes dest=test.txt.{{ lookup('pipe',
'date +%Y%m%d') }}"
host1 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15",
"dest": "./test.txt.20191223",
"gid": 1000,
"group": "ansible",
"md5sum": "d3b07384d113edec49eaa6238ad5ff00",
"mode": "0664",
"owner": "ansible",
"secontext": "unconfined_u:object_r:user_home_t:s0",
"size": 4,
"src": "test.txt",
"state": "file",
"uid": 1000
}
[ansible@target ~]$ ls
test.txt test.txt.20191223 test.txt.4031.2019-12-23@21:29:44~ test.txt.bak
已经创建了test.txt.20191223文件。
如果在lookup插件的第一个参数中指定pipe,您可以将第二个参数的命令执行结果替换为{{ }}。
这很方便。请注意第二个参数是在控制服务器环境中运行的。确保时间同步正确!
合成主机名称和日期
如果最后希望为获取证据而进行备份等操作,可以使用fetch模块进行信息获取,但如果不加思考地进行操作,则会出现以下情况。
[ansible@controll ~]$ ansible host1 -m fetch -a "src=test.txt dest=/home/ansible"
host1 | CHANGED => {
"changed": true,
"checksum": "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15",
"dest": "/home/ansible/host1/test.txt",
"md5sum": "d3b07384d113edec49eaa6238ad5ff00",
"remote_checksum": "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15",
"remote_md5sum": null
}
[ansible@controll ~]$ ls /home/ansible
host1
[ansible@controll ~]$ ls -R /home/ansible/host1
test.txt
dest目录下的/home/ansible下创建了host1/test.txt文件。
fetch模块的基本操作是将文件保存在“dest指定的目录 + 主机名目录 + 文件的完整路径”的层次结构中。这是一个非常好的功能,可以避免文件上的覆盖冲突,但我个人觉得还可以再简洁一点。
因此,我将充分利用fetch模块的flat选项和之前的方法来尝试改进。
[ansible@controll ~]$ ansible host1 -m fetch -a "src=test.txt dest=/home/ansible/test.txt.{{ inventory_host
name }}_{{ lookup('pipe','date +%Y%m%d' )}} flat=yes"
host1 | CHANGED => {
"changed": true,
"checksum": "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15",
"dest": "/home/ansible/test.txt.host1_20191223",
"md5sum": "d3b07384d113edec49eaa6238ad5ff00",
"remote_checksum": "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15",
"remote_md5sum": null
}
[ansible@controll ~]$ ls /home/ansible
host1 test.txt.host1_20191223
inventory_hostname变量存储了当前执行目标节点的名称。
flat选项将src指定的文件放置在dest指定的目录下,但如果不加以处理,可能会导致覆盖冲突。
如果按主机名分类,文件名将不同,因此不会被覆盖。
为了确保,我们可以添加另一台主机进行测试(上面fetch获取的文件已被删除)。
[ansible@controll ~]$ ansible all -m fetch -a "src=test.txt dest=/home/ansible/test.txt.{{ inventory_hostname }}_{{ lookup('pipe','date +%Y%m%d' )}} flat=yes"
host1 | CHANGED => {
"changed": true,
"checksum": "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15",
"dest": "/home/ansible/test.txt.host1_20191223",
"md5sum": "d3b07384d113edec49eaa6238ad5ff00",
"remote_checksum": "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15",
"remote_md5sum": null
}
host2 | CHANGED => {
"changed": true,
"checksum": "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15",
"dest": "/home/ansible/test.txt.host2_20191223",
"md5sum": "d3b07384d113edec49eaa6238ad5ff00",
"remote_checksum": "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15",
"remote_md5sum": null
}
[ansible@controll ~]$ ls /home/ansible
host1 test.txt.host1_20191223 test.txt.host2_20191223
test.txt.host1_20191223和test.txt.host2_20191223已被创建。看起来没问题!
总结
这次使用ansible命令来执行,但是使用playbook也可以很方便地编写出足够使用的内容。
Jinja2很棒,可以简单地解决一些简单的问题。