Gostaria de imprimir os endereços IP e mostrar a saída em formato tabular, incluindo todos os metadados, como valid_lft, temporary, etc.
Descobri que isso ip -j addr show eth0
está me dando o JSON que preciso. Se eu executar, ip -j addr show eth0 | jq -r '.[0].addr_info'
os dados já estarão filtrados para o que estou interessado:
[
{
"family": "inet",
"local": "192.168.x.y",
"prefixlen": 24,
"broadcast": "192.168.1.255",
"scope": "global",
"dynamic": true,
"noprefixroute": true,
"label": "eth0",
"valid_life_time": 2339,
"preferred_life_time": 2339
},
{
"family": "inet6",
"local": "2003:mm:nn:pp:ww:xx:yy:zz",
"prefixlen": 64,
"scope": "global",
"temporary": true,
"dynamic": true,
"valid_life_time": 14342,
"preferred_life_time": 1742
},
{
"family": "inet6",
"local": "2003:mm:nn:pp:qq:rr:ss:tt",
"prefixlen": 64,
"scope": "global",
"dynamic": true,
"mngtmpaddr": true,
"noprefixroute": true,
"valid_life_time": 14342,
"preferred_life_time": 1742
},
{
"family": "inet6",
"local": "fd4e:gg:hh:ii:jj:kk:ll:mm",
"prefixlen": 64,
"scope": "global",
"temporary": true,
"dynamic": true,
"valid_life_time": 14342,
"preferred_life_time": 1742
},
{
"family": "inet6",
"local": "fd4e:gg:hh:ii:qq:rr:ss:tt",
"prefixlen": 64,
"scope": "global",
"dynamic": true,
"mngtmpaddr": true,
"noprefixroute": true,
"valid_life_time": 14342,
"preferred_life_time": 1742
},
{
"family": "inet6",
"local": "fe80::qq:rr:ss:tt",
"prefixlen": 64,
"scope": "link",
"noprefixroute": true,
"valid_life_time": 4294967295,
"preferred_life_time": 4294967295
}
]
Eu sei que posso usar @tsv
para obter um formato de tabela e acomodar diferentes comprimentos de valores para os quais posso canalizar column -ts $'\t'
.
O que não consigo descobrir é como posso iterar por todos os objetos e extrair as chaves primeiro, porque se eu não fizer isso, os valores de saída estarão em colunas incorretas, com base em quais chaves cada objeto tem (ou melhor, não tem). Já consegui extrair as chaves usando
$ ip -j addr show eth0 | jq -r '[.[0].addr_info | .[] | keys_unsorted[]] | reduce .[] as $a ([]; if IN(.[]; $a) then . else . += [$a] end)'
[
"family",
"local",
"prefixlen",
"broadcast",
"scope",
"dynamic",
"noprefixroute",
"label",
"valid_life_time",
"preferred_life_time",
"temporary",
"mngtmpaddr"
]
Agora não sei como combinar tudo isso.
Essencialmente, o seguinte está produzindo o resultado desejado, mas não gosto, porque os cabeçalhos/chaves são definidos manualmente:
$ ip -j addr show eth0 | jq -r '(["Family", "Local", "Prefixlen", "Broadcast", "Scope", "Dynamic", "Noprefixroute", "Label", "Valid_Life_Time", "Preferred_Life_Time", "Temporary", "Deprecated", "Mngtmpaddr"] | (., map(length*"-"))), (.[0].addr_info | .[] | [ .family, .local, .prefixlen, .broadcast, .scope, .dynamic, .noprefixroute, .label, .valid_life_time, .preferred_life_time, .temporary, .deprecated, .mngtmpaddr ] | map(.//"-")) | @tsv' | column -ts $'\t'
Family Local Prefixlen Broadcast Scope Dynamic Noprefixroute Label Valid_Life_Time Preferred_Life_Time Temporary Deprecated Mngtmpaddr
------ ----- --------- --------- ----- ------- ------------- ----- --------------- ------------------- --------- ---------- ----------
inet 192.168.x.y 24 192.168.1.255 global true true eth0 1917 1917 - - -
inet6 2003:mm:nn:pp:ww:xx:yy:zz 64 - global true - - 14348 1748 true - -
inet6 2003:mm:nn:pp:qq:rr:ss:tt 64 - global true true - 14348 1748 - - true
inet6 fd4e:gg:hh:ii:jj:kk:ll:mm 64 - global true - - 14348 1748 true - -
inet6 fd4e:gg:hh:ii:qq:rr:ss:tt 64 - global true true - 14348 1748 - - true
inet6 fe80::qq:rr:ss:tt 64 - link - true - 4294967295 4294967295 - - -
Qualquer ajuda é muito apreciada.
Combinando
jq
(para extrair aaddr_info
matriz da primeira entrada de nível superior) emlr
(para formatação):Se você quiser uma saída CSV simples, altere
--j2p
(JSON-to-pretty-printed) para--j2c
(JSON-to-CSV) e remova a--barred
opção (disponível somente para saída pretty-printed).Tenho certeza de que você pode extrair o
addr_info
array diretamente commlr
, mas isso foi rápido e fácil.O
unsparsify
verbo ofmlr
garante que todos os registros de saída tenham todos os campos e adiciona valores vazios a campos inexistentes (como nobroadcast
campo no segundo registro acima).Dados os seus dados da questão (alimentados diretamente no
mlr
comando acima, pois aaddr_info
matriz já foi extraída), isso produziriaAqui está uma solução alternativa horrível, desajeitada e complicada: execute
ip addr
duas vezes, colete os cabeçalhos da primeira passagem e então analise a segunda:O resultado final, executado no meu sistema, é:
Embora eu usasse
mlr
(ouperl
/python
se você quisesse evitar instalar dependências adicionais comojq
oumlr
), se você tivesse que usarjq
, isso poderia ser feito com algo como:Com sua contribuição, isso dá:
Para adicionar o nome da interface como a primeira coluna: