自定义 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很棒,可以简单地解决一些简单的问题。

bannerAds