シェルスクリプトで次の行を実行すると:
/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
1行に1つのルールでルールのリストを生成します。つまり、各ルールは改行文字で区切られます\n
。一度に1行ずつ入力を処理するには、表示されているオプションとgrep
コマンドを使用します。sed
つまり、改行で区切られた入力を期待し、改行で区切られた出力も生成します。 xargs -0
ただし、nullで区切られた入力が期待されます。前のコマンドの出力にはヌル文字は含まれていないため、xargs
すべての標準入力を単一の項目として一度に読み取ろうとします。これが「パラメータ行が長すぎます」というエラーメッセージが生成される理由です。
解決策は、xargs
改行で区切られた入力を期待するように指示することです。そのためにオプションを追加します-d '\n'
。しかし、我々は一度に1行だけを処理したいと思います。これを行うには、-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
:
-D区切り
入力は指定された文字で終了します。引用符とバックスラッシュは特別ではありません。入力のすべての文字は文字通り処理されます。他のパラメーターと同様に処理されるファイル終了文字列を無効にします。このオプションは、入力が改行で区切られた項目のみで構成されている場合に使用できますが、可能であれば --null を使用するようにプログラムを設計することは、ほぼ常に優れています。指定された区切り文字は、単一文字、Cスタイル文字エスケープ(\ nなど)、または8進数または16進数のエスケープコードです。 8進数と16進数のエスケープコードはprintfコマンドとして理解されます。マルチバイト文字はサポートされていません。-Nmax-args
コマンドラインごとに最大 max-args 個の引数を使用します。サイズを超えると(-sオプションを参照)、-xオプションが指定されていない限り、max-argsよりも少ない引数が使用されます。この場合、xargsは終了します。