xargs: linha de argumento muito longa

1

Quando eu corro abaixo da linha em um script de 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

Tudo o que isso faz é verificar

-A INPUT -s IP -j DROP 

regra em iptables-save .

Diga,

-A INPUT -s 198.55.114.215 -j DROP

Em seguida, converta-o para Delete version e passe para xargs

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

Mas tenho 2000 -A regras em iptables-save e quando tento executá-lo, a linha acima gera um erro:

xargs: argument line too long

Eu verifiquei limites e

echo $(( $getconf ARG_MAX

o resultado é:

2621440

Este erro não ocorre quando há 1000 -A regras, mas 2000 -A regras em iptables-save cria esse problema.

O erro real é a linha:

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

Como posso corrigir esse problema?

    
por NecNecco 15.06.2016 / 02:38

1 resposta

2

Vamos ver o pipeline:

/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 gera uma lista de regras, uma regra por linha. Em outras palavras, cada regra é separada por um caractere de nova linha, \n . Com as opções mostradas, os comandos grep e sed estão processando sua entrada uma linha por vez. Em outras palavras, eles também estão esperando entrada separada por nova linha e produzindo saída separada por nova linha. No entanto, xargs -0 está esperando uma entrada separada. Como a saída dos comandos precedidos não contém nenhum caractere nul, xargs tenta ler todos os seus stdin de uma só vez como um único item. É por isso que gera a mensagem de erro "linha de argumento longa demais".

A solução é informar xargs para esperar entrada separada por nova linha. Para isso, adicionamos a opção -d '\n' . No entanto, também queremos processar apenas uma linha por vez. Para fazer isso, precisamos especificar -n1 . Colocando tudo isso junto:

/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

Documentação

De man xargs :

-d delim
Input items are terminated by the specified character. Quotes and backslash are not special; every character in the input is taken literally. Disables the end-of-file string, which is treated like any other argument. This can be used when the input consists of simply newline-separated items, although it is almost always better to design your program to use --null where this is possible. The specified delimiter may be a single character, a C-style character escape such as \n, or an octal or hexadecimal escape code. Octal and hexadecimal escape codes are understood as for the printf command. Multibyte characters are not supported.

-n max-args
Use at most max-args arguments per command line. Fewer than max-args arguments will be used if the size (see the -s option) is exceeded, unless the -x option is given, in which case xargs will exit.

    
por 15.06.2016 / 04:16