xargs:参数行太长

xargs:参数行太长

当我在 shell 脚本中运行以下行时:

/sbin/iptables-save -t filter | 
grep -- "-A INPUT" | 
grep -v "fail2ban-\|f2b-" | 
sed -e "s#^-A#apply_rule /sbin/iptables -D#g" | 
xargs -0 echo -e "`declare -f apply_rule`\n" | 
/bin/bash

它所做的只是检查

-A INPUT -s IP -j DROP 

统治iptables-save.

说,

-A INPUT -s 198.55.114.215 -j DROP

然后将其转换为Delete版本并传递给xargs

apply_rule /sbin/iptables -D INPUT -s 198.55.114.215 -j DROP

但是我有2000 -A规则iptables-save,当我尝试运行它时,上面的行会抛出错误:

xargs: argument line too long

​我检查了限制并

echo $(( $getconf ARG_MAX

结果是:

2621440

有规则时不会发生此错误1000 -A,但2000 -A有规则时iptables-save会产生此问题。

实际错误是:

xargs -0 echo -e "`declare -f apply_rule`\n"

我该如何解决这个问题?

答案1

我们来看看管道:

/sbin/iptables-save -t filter | 
grep -- "-A INPUT" | 
grep -v "fail2ban-\|f2b-" | 
sed -e "s#^-A#apply_rule /sbin/iptables -D#g" | 
xargs -0 echo -e "`declare -f apply_rule`\n" | 
/bin/bash

iptables生成一个规则列表,每行一个规则。换句话说,每个规则都由换行符 分隔\n。使用如图所示的选项,grepsed命令一次处理一行输入。换句话说,他们还期望换行符分隔的输入并生成换行符分隔的输出。 xargs -0然而期待空分隔的输入。由于前面的命令的输出不包含空字符,因此xargs尝试将其所有标准输入作为单个项目立即读取。这就是为什么它会生成错误消息“参数行太长”。

解决方案是告诉xargs我们期待换行符分隔的输入。为此,我们添加选项-d '\n'。然而,我们也希望它一次只处理一行。为此,我们需要指定-n1.把这一切放在一起:

/sbin/iptables-save -t filter | 
grep -- "-A INPUT" | 
grep -v "fail2ban-\|f2b-" | 
sed -e "s#^-A#apply_rule /sbin/iptables -D#g" | 
xargs -n1 -d '\n' echo -e "`declare -f apply_rule`\n" | 
/bin/bash

文档

man xargs

-ddelim
输入项以指定字符终止。引号和反斜杠并不特殊;输入中的每个字符均按字面意思处理。禁用文件结束字符串,该字符串的处理方式与任何其他参数一样。当输入仅由换行符分隔的项目组成时,可以使用此选项,尽管在可能的情况下设计程序以使用 --null 几乎总是更好。指定的分隔符可以是单个字符、C 样式字符转义符(例如 \n)或者八进制或十六进制转义码。八进制和十六进制转义码被理解为 printf 命令。不支持多字节字符。

-nmax-args
每个命令行最多使用 max-args 个参数。如果超出大小(请参阅 -s 选项),则将使用少于 max-args 的参数,除非给出 -x 选项,在这种情况下 xargs 将退出。

相关内容