![값 중 하나를 건너뛰면서 변수를 반복하는 방법은 무엇입니까?](https://linux55.com/image/117625/%EA%B0%92%20%EC%A4%91%20%ED%95%98%EB%82%98%EB%A5%BC%20%EA%B1%B4%EB%84%88%EB%9B%B0%EB%A9%B4%EC%84%9C%20%EB%B3%80%EC%88%98%EB%A5%BC%20%EB%B0%98%EB%B3%B5%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%80%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
커널 2.6.x 사용
노트:이전 질문에서는 이 작업을 수행하기 위해 bash 배열을 사용하려고 했습니다. 이 운영 체제에서는 sh가 아닌 쉘이 Entware-NG 패키지로 설치되며 스크립트가 실행된 후에 로드되므로 사용할 수 없습니다.
표적:스크립트를 사용하여 iptables 규칙 생성쉿(bash, zsh 등 아님) 형식은 다음과 같습니다. $NAME의 각 인터페이스에 대해...
- $NETID의 해당 위치에서 소스 네트워크 IP 주소에 대한 규칙을 만듭니다. $NAME의 첫 번째 값은 $NETID의 첫 번째 값으로 구성된 소스 네트워크 주소를 갖습니다. 예를 들어, -i eth1은 -src 192.168.10.0/24에 해당하고 -i eth2는 192.168.20.0/24에 해당합니다.
- 원본 네트워크 주소에 사용되지 않는 $NETID의 값에 대한 대상 IP 주소를 만듭니다. 예를 들어 -src 192.168.10.0/24 -dst 192.168.20.0/24입니다.
- 대상 네트워크 주소를 사용하여 각 규칙을 작성하십시오. -dst 값에 여러 주소를 지정하지 마십시오.
원하는 결과:
iptables -I FORWARD -i eth1 -src 192.168.10.0/24 -dst 192.168.20.0/24
iptables -I FORWARD -i eth1 -src 192.168.10.0/24 -dst 192.168.30.0/24
iptables -I FORWARD -i eth2 -src 192.168.20.0/24 -dst 192.168.10.0/24
iptables -I FORWARD -i eth2 -src 192.168.20.0/24 -dst 192.168.30.0/24
iptables -I FORWARD -i eth3 -src 192.168.30.0/24 -dst 192.168.10.0/24
iptables -I FORWARD -i eth3 -src 192.168.30.0/24 -dst 192.168.20.0/24
질문:다음 스크립트는 인터페이스 이름과 -src 값 사이에 1:1 관계를 생성하지 않습니다. 예를 들어 eth1 및 192.168입니다.10.0/24, eth2 및 192.168.20.0/24 등
#!/bin/sh
NETID="10 20 30"
NAME="eth1 eth2 eth3"
for i in $NETID; do
sarg="192.168.$i.0/24"
darg=""
for j in $NETID; do
[ "$i" -eq "$j" ] && continue
darg="192.168.$j.0/24"
for k in $NAME; do
echo "iptables -I FORWARD -i $k -s $sarg -d $darg -j DROP"
done
done
done
답변1
출력 라인의 순서에 대해 걱정하지 않고 POSIX Awk를 사용하십시오.
echo | awk -v 'netids=10 20 30' -v 'names=eth1 eth2 eth3' '
BEGIN {
netidcount = split(netids, netid)
namecount = split(names, name)
if (netidcount != namecount) {
print "Error: You must pass the same number of names and netids."
exit 1
}
for (i in name) {
for (j in name) {
if (i == j) {
continue
}
printf "iptables -I FORWARD -i %s -src 192.168.%s.0/24 -dst 192.168.%s.0/24 -j DROP\n", name[i], netid[i], netid[j]
}
}
}'
물론 이를 변경할 수 있습니다. 예를 들어 위의 awk 스크립트를 파일에 넣고 다음을 사용하여 호출할 수 있습니다.
echo | awk -v ... -v ... -f script.awk
data.txt
또는 네트워크 ID와 이름을 다음 형식으로 입력할 수 있습니다 .
eth1 10
eth2 20
eth3 30
script.awk
그리고 Awk 스크립트 파일을 다음과 같이 작성하세요:
#!/bin/awk
NF != 2 {
error = 1
print "Error: Each line of input must contain one interface name and one number."
exit
}
(($1 in nameseen) || ($2 in netidseen)) {
error = 1
print "Error: Each interface name and network id in input must be unique."
exit
}
{
name[NR] = $1
netid[NR] = $2
nameseen[$1]
netidseen[$2]
}
END {
if (error) {
exit error
}
for (i in name) {
for (j in name) {
if (i == j) {
continue
}
printf "iptables -I FORWARD -i %s -src 192.168.%s.0/24 -dst 192.168.%s.0/24 -j DROP\n", name[i], netid[i], netid[j]
}
}
}
그런 다음 다음과 같이 호출하십시오.
awk -f script.awk data.txt
많은 옵션이 있습니다.
나는 data.txt
다음과 같이 보일 수 있습니다 :
eth1 192.168.10.0/24
eth2 192.168.20.0/24
eth3 192.168.30.0/24
이 데이터 형식을 사용하도록 스크립트를 수정하는 것은 독자의 연습 과제로 남겨집니다. ;)
(참고: 이 코드를 사용하는 경우 이 답변에 대한 링크를 귀속으로 포함하는 것을 잊지 마세요.)
답변2
POSIX sh 버전:
for n in 1 2 3; do
src="$n"0
interface="eth$n"
for dest in 10 20 30; do
[ "$dest" = "$src" ] && continue
printf 'iptables -I FORWARD -i %s -src %s -dst %s -j DROP\n' "$interface" "192.168.$src.0/24" "192.168.$dest.0/24"
done
done
인터페이스를 규칙 소스에 연결하는 방법에 대해 몇 가지 가정을 했습니다. 그러나 그것은 당신이 보여주는 원하는 결과를 만들어냅니다.
답변3
주요 문제는 인터페이스 이름(eth1, eth2, ...)과 관련 네트워크(10.x, 20.x, ...) 사이에 1:1 관계가 있지만 코드에서는 이를 만들지 않는다는 것입니다. 1:1 관계가 성립되었습니다.
어딘가에 ethN
바인딩 해야 합니다. 192.168.N.x
쌍 목록이 포함된 단일 변수를 사용하여 NETS
이를 수행 할 수 있습니다 interface:N
. 아래 내 코드를 참조하십시오.
#!/bin/sh
NETS="eth1:10 eth2:20 eth3:30"
for net in $NETS; do
k="${net%:*}" # Yields the name of the interface
i="${net#*:}" # Yields the number bound to the interface
sarg="192.168.$i.0/24"
for net in $NETS; do
j="${net#*:}" # Yields the number bound to the interface
[ "$i" -eq "$j" ] && continue
darg="192.168.$j.0/24"
echo "iptables -I FORWARD -i $k -s $sarg -d $darg -j DROP"
done
done
노트:
for k in $NAME
달성하려는 목표와 모순되는 것 같아서 루프를 완전히 제거했습니다 .네트워크를 정의에 넣고
NETS
직접 읽을 수도 있습니다. 그것은 다음과 같습니다:sarg
darg
NETS="eth1:192.168.10.0/24 eth2:192.168.20.0/24 eth3:192.168.30.0/24"
[업데이트] 결합다른 질문에 대한 내 대답, 다음 스크립트를 제공합니다.
#!/bin/sh
NETID="10 20 30"
NAME="eth1 eth2 eth3"
NETS=$(set -- $NETID; for iface in $NAME; do echo "$iface:192.168.$1.0/24"; shift; done)
for net in $NETS; do
iface="${net%:*}"
sarg="${net#*:}"
for net in $NETS; do
darg="${net#*:}"
[ "$sarg" != "$darg" ] && echo "iptables -I FORWARD -i $k -s $sarg -d $darg -j DROP"
done
done