![如何以最佳方式从文件中添加 CIDR 以进行设置?](https://linux22.com/image/210724/%E5%A6%82%E4%BD%95%E4%BB%A5%E6%9C%80%E4%BD%B3%E6%96%B9%E5%BC%8F%E4%BB%8E%E6%96%87%E4%BB%B6%E4%B8%AD%E6%B7%BB%E5%8A%A0%20CIDR%20%E4%BB%A5%E8%BF%9B%E8%A1%8C%E8%AE%BE%E7%BD%AE%EF%BC%9F.png)
所以我有几个包含CIDR
条目的文件(例如1.1.1.0/24
)。任务是NFTables
使用 bash 脚本将这些文件中的条目添加到一组。在这样做时,我仅限于OpenWRT
公用事业。
问题是这些文件中可能有很多条目,并且它们可能会耗尽条目的限制每个命令 4096 个字符。而且这些文件会自动更新cron
,因此也需要定期删除和重新填充一组文件。
在我看来,有一种比我已经做到的更简单的方法。我还想减少这个混乱的执行时间。这是我的尝试。
nft add element $TARGET_SET { $(awk '{print $1 ", "}' "$CUSTOM_CIDRS_FILE") }
这里还有一个问题,如果我的文件有大量条目,我会克服每个命令 4096 个字符的限制吗?最后一个问题,如果我在循环中一次添加一个条目,形成一组是否需要很长时间?
我主要等待经过良好实践的答案。
答案1
awk
可以构建一个要执行的字符串,该字符串可以保持在特定长度以下;这无疑比
xargs
必须分叉echo ... | tr
管道更有效。
#!/usr/bin/env awk
{
len = length()
if (len > limit) {
if (length(outbuf)) {
system("echo " ENVIRON["TARGET_SET"] outbuf)
}
outbuf = $0
# the limit will be 4096 minus the length of the rest of
# the command and if the 4096 is kern.argmax then you
# may need to subtract even more to account for the
# length of the environment variables!
limit = 6
} else {
# join another field to output buffer
outbuf = outbuf "," $0
}
# the plus is for the length of the field joiner
limit -= len + 1
}
END {
if (length(outbuf)) {
system("echo " ENVIRON["TARGET_SET"] outbuf)
}
}
该脚本中的内容"echo "
用于测试,可能会运行合适的nft ...
命令。TARGET_SET
必须导出以便awk
可以从环境中读取它。
答案2
您在哪里读到过 nftables 命令中 4096 个字符的限制?如果我有 4000 个 CIDR 范围的列表(几乎 64,000 个字符),我可以运行您的命令而不会出现错误:
# wc -l ranges.txt
400.0 ranges.txt
# export TARGET_SET=example_set
# export CUSTOM_CIDRS_FILE=ranges.txt
# nft add set ip filter $TARGET_SET { type ipv4_addr\; flags interval\; }
# nft add element $TARGET_SET { $(awk '{print $1 ", "}' "$CUSTOM_CIDRS_FILE") }
这些nft add
命令运行大约 0.003 秒,包含 4000 个元素。
似乎在某些时候我们可能会遇到 Linux 命令行长度限制,在这种情况下我们可以批量处理。这将以 1000 个为批次添加元素:
xargs -n1000 sh -c '
nft add element ip filter $TARGET_SET { $(
echo "$@" | tr " " ","
) }' -- < $CUSTOM_CIDRS_FILE
(请注意,上面假设TARGET_SET
是环境变量,而不是 shell 变量。)
对于相同的 4000 个元素,运行时间约为 0.1 秒。