我想在交互式 shell 中依次运行这两个命令(以 root 身份并加载“过滤器”表和“输入”链):
nft define lala=1.2.3.4
nft add rule ip filter input ip saddr \$lala accept
您可以看到我转义了“$”以避免 shell 扩展。但我收到此错误消息“未知标识符‘lala’”。如果我不转义“$”,则会收到此错误消息:“语法错误,意外接受”。如果我写\$$啦啦相反,我收到这个错误消息:“语法错误,未预期的接受,预期字符串”,并且显示这个错误规则:添加规则 ip 过滤器输入 ip saddr $ accept。
那么,在交互式 shell 中使用 Nft 变量的正确语法是什么?在 Nft 脚本中执行相同操作效果很好(无需担心转义)。
多谢
答案1
符号变量正在使用nft
用户空间命令被解析为其值仅有的通过此命令。该nft
命令将变量解析为其指定的值以组合最终结果。然后该nft
命令使用网络链接接口与内核通信并向其发送要添加的新规则。内核绝不看不到lala=1.2.3.4
,也没有任何符号变量的概念。
因此,如果你将nft
命令分成两次调用,则会发生以下情况:
第一个
nft
命令定义了一个符号变量以供自己以后使用。但是没有做其他事情。它甚至不必与内核通信,因为没有要求更改规则集。(实际上它确实进行了通信,但是发送了“无”内容,就像使用命令一样nft ''
)。在命令结束时,符号的定义会丢失,因为尚未使用。该命令的第二次调用
nft
需要解析$lala
符号,但找不到定义:nft
因错误而停止。
所以这一切都必须在一 nft
调用,因此第二条语句仍然知道符号变量。有多种方法可以做到这一点。我在下面的示例中保留了nft
不应输入的 shell 和 提示。
交互的
nft
-i, --interactive
从交互式 readline CLI 读取输入。您可以使用quit
退出,或者使用 EOF 标记,通常是 CTRL-D。# nft -i nft> define lala=1.2.3.4 nft> add rule ip filter input ip saddr $lala accept nft> quit
一次
nft
调用即可执行两个命令。# nft 'define lala=1.2.3.4; add rule ip filter input ip saddr $lala accept'
请注意,需要额外的
;
,因为在这种情况下,nft
它接收一行参数,但它们应该拆分成两个逻辑命令。它还nft
拥有自己的解析器,因此它不关心命令是作为单个命令参数还是多个单独的参数接收的。在这里,所有内容都包含在一对 中,''
以避免出现;
和$
字符的 shell 问题。然后
nft
有一个从文件读取的选项。从文件读取时,所有输入都是同一nft
命令上下文的一部分。-f, --file filename
从文件名读取输入。如果文件名为 -,则从标准输入读取。nft 脚本必须启动
#!/usr/sbin/nft -f
因此,有一个名为的文件
test.nft
具有以下内容:define lala=1.2.3.4 add rule ip filter input ip saddr $lala accept
然后就可以使用它:
# nft -f test.nft
下面的变体在“nftables语言”。
test.nft
文件内容如下:#!/usr/sbin/nft -f define lala=1.2.3.4 add rule ip filter input ip saddr $lala accept
然后:
# chmod a+rx test.nft # ./test.nft
这也行得通:
# nft -f - <<'EOF' > define lala=1.2.3.4 > add rule ip filter input ip saddr $lala accept > EOF
对于每个先前的命令,生成的规则集是相同的(假设表和链之前已创建):
# nft list chain ip filter input
table ip filter {
chain input {
type filter hook input priority filter; policy accept;
ip saddr 1.2.3.4 accept
}
}
不会再留下任何痕迹$lala
:内核从未收到过任何东西$lala
,而只1.2.3.4
收到它所回馈的东西。