쉘 스크립트에서 다음 줄을 실행하면:
/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
. 한 번에 한 줄씩 입력을 처리하려면 표시된 옵션 grep
과 명령을 사용하십시오. sed
즉, 개행으로 구분된 입력을 기대하고 개행으로 구분된 출력도 생성합니다. xargs -0
그러나 null로 구분된 입력이 예상됩니다. 이전 명령의 출력에는 널 문자가 포함되어 있지 않으므로 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
:
-디구분
입력은 지정된 문자로 종료됩니다. 따옴표와 백슬래시는 특별하지 않습니다. 입력의 모든 문자는 문자 그대로 처리됩니다. 다른 매개변수처럼 처리되는 파일 끝 문자열을 비활성화합니다. 이 옵션은 입력이 개행으로 구분된 항목으로만 구성되어 있을 때 사용할 수 있지만 가능하면 --null을 사용하도록 프로그램을 설계하는 것이 거의 항상 더 좋습니다. 지정된 구분 기호는 단일 문자, C 스타일 문자 이스케이프(예: \n) 또는 8진수 또는 16진수 이스케이프 코드일 수 있습니다. 8진수 및 16진수 이스케이프 코드는 printf 명령으로 이해됩니다. 멀티바이트 문자는 지원되지 않습니다.-Nmax-args
명령줄당 최대 max-args개의 인수를 사용합니다. 크기가 초과되면(-s 옵션 참조), -x 옵션이 제공되지 않는 한 max-args보다 적은 인수가 사용되며, 이 경우 xargs가 종료됩니다.