Mac 的回归

作者: Kyle Rankin

之前的文章中,我谈到了 vim 宏的基础知识。在那篇文章中,我描述了如何录制自定义宏,将其分配给一个键,然后使用它对 BIND 区域进行自动化编辑。我还预告说,我将在未来的文章中介绍更高级的宏用法,例如嵌套宏。我短暂地绕道介绍了几个不同的主题,但现在我回到了主题,在本文中,我将讨论宏更复杂的用法。

我喜欢使用 BIND 区域文件作为宏示例,因为这是我自己最常使用宏的文件。因为多人经常编辑区域文件,他们可能不都具有相同的格式。此外,区域文件的顶部通常具有与文件其余部分不同的多行格式。在我 2014 年 7 月的文章中,我谈到了如何使用单个宏在区域文件中添加 50 个连续的 A 记录,但是当我要执行更复杂的编辑,或者如果我必须在某些文件中选择性地执行编辑而不是在其他文件中执行编辑时,我发现将几个不同的简单宏记录在不同的键下很有用,然后记录一个新的宏,该宏只是以特定顺序调用这些其他宏。 除此之外,这使我可以根据需要更改一些较短的宏,而无需重新录制所有内容。

对于第一个示例,让我们看一下我上次使用的 BIND 区域文件的更完整版本


;
; BIND data file for example.com
;
$TTL 15m
@       IN      SOA     example.com. root.example.com. (
                        2014081500
                        10800
                        1200
                        7200
                        7200 )
;
example.com.   IN      NS      ns1.example.com.
example.com.   IN      NS      ns2.example.com.
;
ns1      IN A  10.9.0.5
ns2      IN A  10.9.0.6
;
worker1  IN A  10.9.0.15
worker2  IN A  10.9.0.16
worker3  IN A  10.9.0.17
. . .
worker50 IN A  10.9.0.64

在此示例中,假设我有 15 个不同区域的区域文件,但我希望对所有区域文件进行相同的编辑。我想将文件中的 TTL 更改为 10 分钟,并且需要将域的联系信息从 root@domain 更改为 dnsadmin@domain。我还需​​要增加区域文件中的序列号 (2014081500),并且我需要将名称服务器 IP 全部更改为指向位于 10.1.0.250 和 10.1.0.251 的一组新名称服务器,最后,我想为每个区域文件添加 50 个 worker。

虽然我想象我可以将所有这些构建到一个大的宏中,但对我来说,将步骤分解为至少四个我已经预先分配了字母的宏是有意义的

  • 宏 t 将更改 TTL。

  • 宏 s 将更改联系信息并增加序列号。

  • 宏 n 将更新名称服务器记录。

  • 宏 w 将添加一个 worker。

因为我要将这些宏链接在一起,所以比过去更重要的是,我确保我的光标首先锚定在已知位置。对于第一个宏,这意味着从 gg 开始移动到文件的最顶部,而对于最后一个宏,我将要键入 G 以移动到文件的底部。在每个阶段,非常重要的是您测试每个宏,然后撤消更改并确认您的宏完全按照您的预期工作。让我们分解每个宏。

对于宏 t,我首先键入 qt 进入宏模式并将宏分配给 t 键。然后我键入 gg 以确保我位于文件的顶部。接下来,我键入 /TTL <Enter> 将光标移动到 TTL 行。然后我键入 w 向前移动一个单词到我要更改的实际 TTL 值,然后我键入 cw10m 将后面的单词从 15m 更改为 10m。最后,我按 Esc 退出插入模式,然后按 q 退出宏。然后,完整的宏键击组合将是 qtgg/TTL <Enter> wcw10m <Esc> q。记录宏后,我键入 u 撤消我的更改,然后通过键入 @t 测试宏。

对于宏 s,我键入 qs 进入宏模式并将宏分配给 s 键。然后我再次键入 gg 以锚定到文件的顶部。接下来,我键入 /SOA <Enter> 移动到 SOA 行。然后我键入 /root <Enter> 移动到 root.example.com 的开头,然后键入 cwdnsadmin <Esc> 将该单词更改为 dnsadmin 并退出插入模式。接下来,我键入 ^j 将光标移动到下一行的开头。最后,我键入 w <Ctrl-a> 向前移动到序列号并递增它,然后按 q 退出宏模式。完整的宏键击组合变为 qsgg/SOA <Enter> /root <Enter> cwdnsadmin <Esc> ^jw <Ctrl-a> q。再次,我保存宏并使用 u 撤消更改并使用 @s 重放它,以确保它执行我期望的操作。

对于宏 n,我键入 qn 进入宏模式并将宏分配给 n 键。然后我键入 gg 以锚定到文件的顶部。接下来,我键入 /^ns1 <Enter> 移动到配置名称服务器的行。此时,我可以采用几种方法来编辑这些行。我的偏好是键入 /IN A <Enter> 2w,这将使我的光标移动到 IP 的开头。然后我键入 c$10.1.0.250 <Esc> 以编辑到行尾并退出插入模式。

由于 ns2 与 ns1 非常相似,所以我可以只键入 yyp <Ctrl-a> $ <Ctrl-a> 来复制和粘贴 ns1,将 ns1 递增为 ns2,然后移动到行尾并递增 IP。接下来,我需要找到现有的 ns2 行并使用 /^ns2 <Enter> dd 删除它。最后,我可以键入 q 保存宏。完整的宏是 qngg/^ns1 <Enter> /IN A <Enter> 2wc$10.1.0.250 <Esc> yyp <Ctrl-a> $ <Ctrl-a> /^ns2 <Enter> ddq。尽管这看起来像很多文本,但是当您必须在多个文件上重复这些步骤时,它将节省大量工作。

对于最后一个宏 w,我键入 qw 进入分配给 w 键的宏模式,然后键入 G 这次移动到文件的底部。然后我键入 /^worker <Enter> N 搜索下一个 worker(这将环绕到顶部,然后 N 将移回文件中的最后一个 worker)。最后,我键入 yyp 复制并粘贴该行,然后 <Ctrl-a> $ <Ctrl-a> 递增 worker 主机名和 IP。最后,我键入 q 退出宏模式。完整的宏是 qwG/^worker <Enter> Nyyp <Ctrl-a> $ <Ctrl-a> q。像其他宏一样,我使用 @w 测试几次,并在两次测试之间使用 u 撤消所有更改,直到我对它的工作方式感到满意为止。

现在我已经记录了所有这些宏,我可以只打开每个文件并键入 @t 以更新 TTL,@s 以编辑联系信息和序列号,@n 以更新名称服务器,然后键入 50@w 以添加 50 个 worker。

因为我将在许多文件上执行相同的步骤,所以我不妨将所有这些命令捕获到一个新的宏中,我将其分配给 c。为此,我只需键入 qc 进入分配给 c 键的宏模式,然后键入 @t@s@n50@w 以执行所有先前记录的宏。最后,我键入 q 退出宏模式。完整的击键组合是 qc@t@s@n50@wq,以将以上所有击键组合分配给单个宏。现在,当我打开下一个文件时,我可以只键入 @c 来执行完整的步骤列表。

现在,除了节省一些击键之外,以这种方式嵌套宏还有其他充分的理由。因为我将每个逻辑步骤都保存为自己的宏,所以我可以独立地调整或修改以上任何宏,将新宏保存到相同的键,并且包括最终组合宏在内的所有其他宏都可以保持不变。

假设在我记录了所有这些宏之后,我意识到我弄错了名称服务器的 IP 地址。我所要做的就是记录分配给同一 n 键的新宏,一旦完成,我仍然可以使用 @c 对文件进行完整的更改集。

我希望您发现这些示例很有用,并且希望下次您必须对许多文本文件执行一系列单调乏味的编辑时,您可以使用 vim 宏节省一些击键次数。

Kyle Rankin 是 Linux Journal 的技术编辑和专栏作家,也是 Purism 的首席安全官。他是 Linux Hardening in Hostile Networks, DevOps Troubleshooting, The Official Ubuntu Server Book, Knoppix Hacks, Knoppix Pocket Reference, Linux Multimedia HacksUbuntu Hacks 的作者,也是许多其他 O'Reilly 书籍的贡献者。Rankin 经常在 BsidesLV、O'Reilly Security Conference、OSCON、SCALE、CactusCon、Linux World Expo 和 Penguicon 等会议上就安全和开源软件发表演讲。您可以在 @kylerankin 上关注他。

加载 Disqus 评论