Estou tentando usar o awk com a saída de ss para imprimir a quarta coluna. Às vezes funciona, mas outras vezes mescla ou divide as colunas incorretamente. Eu tentei algumas opções diferentes para FS, aqui são dois ou mais espaços porque os cabeçalhos dos campos contêm um único espaço.
Isso está me dando a quinta coluna e um cabeçalho em branco:
$ ss -tn
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 36 172.31.19.34:22 172.115.128.85:64478
ESTAB 0 0 [::ffff:172.31.19.34]:80 [::ffff:172.115.128.85]:65446
$ ss -tn | awk -F '[[:space:]][[:space:]]+' '{print $4}'
172.115.128.86:64478
[::ffff:172.115.128.86]:65446
O mesmo comando aqui está me dando a quarta coluna, é isso que eu quero.
$ ss -tn
State Recv-Q Send-Q Local Address:Port Peer Address:Port
ESTAB 0 36 172.31.19.34:22 172.115.128.85:64478
$ ss -tn | awk -F '[[:space:]][[:space:]]+' '{print $4}'
Local Address:Port
172.31.19.34:22
Eu sei cut
que pode ser mais fácil, mas estou usando awk
porque quero fazer mais processamento.
Para adicionar detalhes: não sei por que ss está mostrando esse endereço estilo IPv6. Esta é uma conexão do meu laptop ao servidor Apache, mas meu laptop não possui um endereço IPv6.
Responder1
Comomurusugerido em umComente, awk
provavelmente está funcionando de forma consistente. O que pode variar é o espaçamento na saída do arquivo ss
.
Acontece que ss -nt
1 gera sete colunas, cujos cabeçalhos são: State
, Recv-Q
, Send-Q
, Local Address
, Port
, Peer Address
, Port
. A quarta e a quinta colunas são separadas por dois pontos ( :
); a mesma coisa para o sexto e o sétimo. Todos os outros são separados por um caractere de espaço.
Todas as colunas são preenchidas com espaços quando necessário para alinhamento. O quarto e o sexto são preenchidos à esquerda, todos os outros à direita.
Mais preenchimento pode acontecer:
Se a saída de
ss -nt
for direcionada para um terminal:se o comprimento mínimo de suas linhas, calculado como a soma do conteúdo mais longo de cada campo mais o espaçamento mínimo (seis caracteres), for menor que a largura do terminal, cada linha será expandida até a largura do terminal por preenchimento uniforme todas as colunas com espaços;
caso contrário, as linhas serão quebradas e os campos serão alinhados entre as linhas (preenchidos como acima, até a largura do terminal).
Se a saída de
ss -nt
não for direcionada para um terminal (por exemplo, for canalizada ou redirecionada para um arquivo normal), o comprimento real das linhas será definido como o múltiplo mínimo de 80 que é maior que o comprimento mínimo definido acima. Todas as colunas são preenchidas uniformemente com espaços para atingir um comprimento total de linha que será consequentemente de 80, 160, 240, ... caracteres 2 .
Assim, não há garantia de que duas colunas serão separadas por dois ou mais espaços, tornando essa sequência não confiável para divisão.
No entanto, você pode lidar com a saída de ss -tn
uma maneira razoavelmente segura, observando que os cabeçalhos das colunas são conhecidos e fixos e que, exceto os cabeçalhos, nenhuma de suas colunas deve incluir espaços 3 :
ss -nt | sed '
1 s/[ ]Address:/_Address|/g # Remove the known spaces from column
# headers; also, change ":" into "|"
s/:\([^:|]*[ ]\)/|\1/g # Change the colons used as separators
# into vertical bars "|", to avoid
s/:\([^:|]*\)$/|\1/g # confusion with those in IPv6s
' | awk -v FS='\\||[ ]+' -v OFS=":" ' # Split on sequences of one or more
{ print $4,$5 } # spaces OR on any vertical bar
'
Isso imprimirá apenas a quarta e a quinta colunas (endereço local e porta), separadas por dois pontos. Observe que, usando um separador de campo que não seja o espaço único padrão, awk
identificará oito colunas em vez de sete e, se você fizer um { $1=$1; print; }
, imprimirá um OFS
no final de qualquer linha para a qual a última coluna seja preenchida à direita com pelo pelo menos um espaço.
1 Outras opções (por exemplo -i
, -e
, -m
) alteram drasticamente a saída de ss
. Por questões de brevidade e clareza, focaremos apenas neste comando exato.
2 Aproximado e possivelmente inexato. Mas isso não é relevante para o ponto desta pergunta/resposta.
3 Aparentemente isto não é garantido, deliberadamente não tentaremos cobrir todos os casos menos habituais.
Responder2
Por que o separador de campos awk não está funcionando de forma consistente?
É, o que não é confiável é o número de espaços na saída de ss
.
a quarta coluna, é isso que eu quero.
Depois é só remover o cabeçalho ( -H
) e selecionar a quarta coluna:
$ ss -taH | awk '{print $4}'
172.31.19.34:22
[::ffff:172.31.19.34]:80
Como o cabeçalho está fixo, basta adicioná-lo novamente (se necessário):
$ echo "Local Address:Port"
Local Address:Port
Comando completo:
$ echo "Local Address:Port"; ss -tnH | awk '{print $4}'
Local Address:Port
172.31.19.34:22
[::ffff:172.31.19.34]:80
Sim, seu computador sempre possui endereços IPv6 (um ou vários). Caso não os queira, peça apenas os endereços IPv4:
$ ss -tnH4 | awk '{print $4}'
172.31.19.34:22