Na verdade, isso é para um cluster Redis. Tenho 3 IPs mestres e 3 IPs escravos. Preciso produzir 3 pares de endereços IP onde os endereços do par estão em sub-redes /24 diferentes.
Ou em outras palavras, dada uma lista de n
endereços IP ( n
sendo um número par e não mais da metade dos endereços IP estando na mesma /24
sub-rede), como particioná-los em n
pares /2 onde os dois endereços em cada par estão em diferentes sub-redes /24?
Os pares devem ser armazenados como chave e valores de um ip_map
array associativo. Por exemplo, dada uma lista de endereços IP armazenados em um $ips
array:
ips=(
"172.211.91.63"
"172.211.90.61"
"172.211.91.30"
"172.211.90.173"
"172.211.89.233"
"172.211.89.166"
)
O resultado poderia ser:
declare -A ip_map=(
[172.211.91.63]=172.211.90.61
[172.211.91.30]=172.211.89.233
[172.211.90.173]=172.211.89.166
)
Intuitivamente, eu acho que se você classificar seus endereços IP em buckets, um para cada sub-rede, e continuar escolhendo 2 dos 2 buckets mais cheios, isso deve permitir que você os emparelhe todos. Poderia ser com algo como:
O que na sua amostra dá:
code for @ARGV
faz um loop sobre os parâmetros fornecidos ao script inline (a-e
xpression) usando a$_
variável padrão como a variável do loop. Uma forma mais curta dofor (@ARGV) {code}
.s/\.\d+$//r
(que atua$_
por padrão) remove a.<digits>
parte no final, mas com or
sinalizador, o resultado ér
retornado em vez de ser armazenado de volta em$_
. Então isso se expande para a parte da sub-rede /24 do endereço IP.%s
array associativo (também conhecido como hash emperl
), onde$s{subnet}
é uma referência à lista de endereços IP naquela sub-rede.@{that}
desreferencia -o para que possamos adicionarpush
o endereço IP ($_
) na lista.@l = values %s
: obtém os valores do hash, ou seja, referências às nossas listas de buckets em uma@l
lista.@$b <=> @$a
, ela se expande para o número de elementos nela, então comparamos o comprimento das listas para classificá-las) e entãopop
executamos ping em um da primeira e segunda listas (pop(@{$l[...]})
).Você avaliaria a saída no bash (com
source <(that-code)
oueval "$(that-code)"
), mas também pode usarperl
para a coisa toda, shells (especialmente o bash) não são muito bons em programação.Se eu tivesse que usar um shell, usaria zsh em vez de bash, onde algo equivalente poderia ser assim:
Matrizes associativas zsh, como as do bash, não podem conter listas. Aqui, estamos armazenando a lista de endereços IP separados por espaços (para que possamos usar
(w)
indexação baseada em ord mais tarde) nos valores da matriz associativa e prefixados com uma sequência dex
caracteres s (usada um pouco como 𝍩 𝍪 𝍫 𝍬 𝍸 marcas de contagem), um por endereço IP, então fica assim:Então, o
${(O)l}
que usamos paraO
ordenar a lista em ordem léxica reversa classifica por número de elementos. Opop
ping é feito extraindo e removendo os últimos endereços IP nesses buckets e removendo umx
do início.