AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 786340
Accepted
ZacWolf
ZacWolf
Asked: 2024-11-09 06:01:57 +0800 CST2024-11-09 06:01:57 +0800 CST 2024-11-09 06:01:57 +0800 CST

Tentando analisar a saída do comando "lastb" via awk, mas quando o campo userID está em branco, minhas variáveis ​​são descartadas

  • 772

Estou tentando extrair a data e o endereço IP da saída delastb

Estou usando:lastb | awk '{print $5,$6,$7,$3}'

O problema é que às vezes a primeira coluna (userID) lastbfica em branco:

Exemplo de dados:

wpsadmin ssh:notty 213.109.202.127 Ter 1 Out 12:07 - 12:07 (00:00)
         ssh:notty 8.219.222.66 Terça, 1º de outubro, 11h48 - 11h48 (00h00)
quser ssh:notty 213.109.202.127 Terça, 1º de outubro, 11h03 - 11h03 (00h00)
udatabas ssh:notty 139.19.117.130 Ter Out 1 10:34 - 10:34 (00:00)
Admin ssh:notty 213.109.202.127 Terça, 1º de outubro, 09:58 - 09:58 (00:00)
         ssh:notty 79.110.62.93 Terça, 1º de outubro, 09:40 - 09:40 (00:00)
udatabas ssh:notty 139.19.117.130 Ter Out 1 09:34 - 09:34 (00:00)

...o que desequilibra minhas variáveis ​​awk em uma.

Então, usar: lastb | awk '{print $5,$6,$7,$3}'para o conjunto de dados acima me dá:

1 de outubro 12:07 213.109.202.127
1 11:48 - Ter
1 de outubro 11:03 213.109.202.127
1 de outubro 10:34 139.19.117.130
1 de outubro 09:58 213.109.202.127
1 09:40 - Ter
1 de outubro 09:34 139.19.117.130

Como retifico isso? Obrigado!

bash
  • 5 5 respostas
  • 111 Views

5 respostas

  • Voted
  1. Ed Morton
    2024-11-09T19:57:46+08:002024-11-09T19:57:46+08:00

    Basta contar os números dos campos que você deseja imprimir a partir do final ( NF) em vez do início dos campos, por exemplo, usando qualquer awk:

    $ lastb | awk '{print $(NF-5), $(NF-4), $(NF-3), $(NF-7)}'
    Oct 1 12:07 213.109.202.127
    Oct 1 11:48 8.219.222.66
    Oct 1 11:03 213.109.202.127
    Oct 1 10:34 139.19.117.130
    Oct 1 09:58 213.109.202.127
    Oct 1 09:40 79.110.62.93
    Oct 1 09:34 139.19.117.130
    
    • 4
  2. Prabhjot Singh
    2024-11-09T16:58:58+08:002024-11-09T16:58:58+08:00

    Usando awk:

    $ awk '{split($0,a,/ssh:[^[:space:]]+/);$0= a[2]}{print $3,$4,$5,$1}'
    
    $ awk '$1 !~ /ssh:/{$1="";$0=$0}{print $4,$5,$6,$2}'
    
    • 1
  3. Best Answer
    Stéphane Chazelas
    2024-11-09T21:23:35+08:002024-11-09T21:23:35+08:00

    Em awk, o valor padrão de FSé um único caractere de espaço, e esse valor tem um significado muito especial. Isso significa que os campos são separados por sequências de um ou mais caracteres em branco¹, mas também que espaços em branco à esquerda e à direita são ignorados.

    Aqui você não quer fazer a segunda parte, para a qual você pode fazer:

    $ lastb | awk -F '[[:blank:]]+' '{print $5,$6,$7,$3}'
    Oct 1 12:07 213.109.202.127
    Oct 1 11:48 8.219.222.66
    Oct 1 11:03 213.109.202.127
    Oct 1 10:34 139.19.117.130
    Oct 1 09:58 213.109.202.127
    Oct 1 09:40 79.110.62.93
    Oct 1 09:34 139.19.117.130
    

    Aqui, FS(conforme definido com a -Fopção) being [[:blank:]]+, significa que qualquer sequência de um ou mais espaços em branco constitui um separador Fde campo S, incluindo aqueles no início da linha. Se uma linha começa com um espaço em branco, isso significa que $1será a string vazia antes desses espaços em branco.

    Isso pressupõe que os 3 primeiros campos não contenham espaços em branco. Na prática, isso não pode ser garantido. Acho que com tentativas de login ssh com falha, nem mesmo novas linhas são escapadas, então é difícil analisar essa saída de forma confiável.

    Eu posso fazer ssh -l $'a b\nc' localhoste a lastbsaída terá:

    a b
    c    ssh:notty    127.0.0.1        Sun Nov 10 14:57 - 14:57  (00:00)
    chazelas seat0        login screen     Fri Oct 25 08:19 - 08:19  (00:00)
    

    (veja também aquela tentativa genuína fracassada onde o terceiro campo login screencontém um espaço).

    No entanto, não posso fazer com que um :seja incluído no campo de nome de usuário.

    Então a abordagem do @EdMorton de contar campos a partir do final seria melhor aqui, e ainda mais confiável se você verificasse se a linha contém [[:blank:]]ssh:para filtrar entradas que não sejam por sshd, ou as primeiras linhas do nome de usuário para aqueles nomes de usuário que contêm novas linhas.

    lastb | awk '/[[:blank:]]ssh:/ {print $(NF-5), $(NF-4), $(NF-3), $(NF-7)}'
    

    Para sua informação, o lastbutilitário já foi removido do Debian desde maio de 2024 (o que me parece prematuro, já que a maioria das coisas ainda registra entradas em wtmp/ btmpe poucas coisas ainda em wtmpdb; parece que faz parte da pressa para corrigir o problema Y2038 ), então confiar nele pode não ser uma garantia para o futuro, veja a NEWSentrada relacionada no util-linuxpacote Debian:

    util-linux(2.40.1-2) instável; urgência=média

    • last(1) foi dividido para o wtmpdbpacote. Se você achar last(1) útil, instale wtmpdbe aceite as alterações de configuração padrão do PAM de libpam-wtmpdb.

    • lastb(1) foi removido. Consulte syslog/journal para tentativas de login com falha.

      -- Chris Hofstaedtler < [email protected] > Qua, 29 de maio de 2024 23:52:19 +0200

    (você também precisa instalar o que é recomendadolibpam-wtmpdb apenas por , não é uma dependência física).wtmpdb

    Obter o registro de data e hora (em formato padrão analisável com precisão de microssegundos como bônus²) e o endereço de origem para tentativas de autenticação SSH com falha journalctlpoderia ser algo como:

    journalctl -qaro short-iso-precise --no-hostname -u ssh.service \
      -g '^Failed .* user .* from [\d.]+ port \d+ ssh\d*\z' |
      sed -E 's/ .* from( [^ ]+).*/\1/'
    

    Ou para alguma saída JSON para facilitar o pós-processamento:

    journalctl -qaro json \
      --output-fields=_SOURCE_REALTIME_TIMESTAMP,MESSAGE \
      -u ssh.service \
      -g '^Failed .* user .* from [\d.]+ port \d+ ssh\d*\z' |
      jq -c '
        {
          "ts": (
            ._SOURCE_REALTIME_TIMESTAMP as $t |
            $t[0:-6] |
            tonumber |
            strflocaltime("%FT%T." + $t[-6:] + "%z")
          )
        } + (
          .MESSAGE |
            capture(" user (?<user>.*) from (?<ip>[^ ]+) port (?<port>\\d+)")
        ) |
         .port |= tonumber'
    

    O que dá algo como:

    {"ts":"2024-11-10T19:26:12.952796+0000","user":"\\377\\377\\377\\377\\377\\377\\377\\377","ip":"127.0.0.1","port":42126}
    {"ts":"2024-11-10T19:23:52.749940+0000","user":"\\001\\002\\003\\004\\005\\006\\r\\v\\t","ip":"127.0.0.1","port":47172}
    {"ts":"2024-11-10T19:18:57.094019+0000","user":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","ip":"127.0.0.1","port":59338}
    {"ts":"2024-11-10T17:11:17.574040+0000","user":"\\351","ip":"127.0.0.1","port":46272}
    {"ts":"2024-11-10T14:58:46.607290+0000","user":"a b c d e f\\nc","ip":"127.0.0.1","port":57374}
    {"ts":"2024-11-10T14:57:31.148206+0000","user":"a b\\nc","ip":"127.0.0.1","port":35566}
    {"ts":"2024-11-10T14:56:40.154428+0000","user":"a","ip":"127.0.0.1","port":51774}
    {"ts":"2024-11-10T14:55:57.128920+0000","user":"foo bar\\nbaz","ip":"127.0.0.1","port":39012}
    {"ts":"2024-11-10T14:50:07.156848+0000","user":"foo\\nbar","ip":"127.0.0.1","port":55176}
    {"ts":"2024-11-10T14:48:52.938861+0000","user":"root ssh ssh         127.0.0.1        Sun Nov 10 14.38 _ 14.38   00.00\\nbar","ip":"127.0.0.1","port":38166}
    {"ts":"2024-11-10T14:34:17.532900+0000","user":"root ssh","ip":"127.0.0.1","port":55498}
    {"ts":"2024-11-10T14:29:01.636760+0000","user":"x\\ny","ip":"127.0.0.1","port":54132}
    {"ts":"2024-11-10T14:28:43.724771+0000","user":"foo bar","ip":"127.0.0.1","port":37306}
    {"ts":"2024-11-09T15:40:59.024960+0000","user":"stephane","ip":"172.17.27.2","port":52536}
    {"ts":"2024-11-09T15:40:35.582616+0000","user":"qweq","ip":"172.17.27.2","port":54234}
    

    (também usado _SOURCE_REALTIME_TIMESTAMPpara obter o horário em que o evento foi gerado, em vez de recebido).

    Onde você vê minhas tentativas anteriores de enganar lastbsendo tratadas de uma forma mais útil do que por lastb, até mesmo lastb --time-format=iso -w.


    ¹ por POSIX, isso é nova linha ou qualquer caractere para o qual iswblank()retorna verdadeiro, mas você descobrirá em algumas awkimplementações, que é qualquer caractere para o qual iswspace()retorna verdadeiro ( espaço sendo um superconjunto de espaço em branco que inclui nova linha e outros espaços em branco verticais, como retorno de carro, avanço de formulário, tabulação vertical...). Para aqueles que não suportam codificações multibyte, são apenas as de byte único ( isblank()/ isspace()).

    ² Veja também lastb --time-format=isopara obter esse formato com lastbprecisão de subsegundos, embora sem ela.

    • 1
  4. markp-fuso
    2024-11-09T06:26:54+08:002024-11-09T06:26:54+08:00

    Para simular lastba chamada do OP:

    $ cat lastb.out
    wpsadmin ssh:notty    213.109.202.127  Tue Oct  1 12:07 - 12:07  (00:00)
             ssh:notty    8.219.222.66     Tue Oct  1 11:48 - 11:48  (00:00)
    quser    ssh:notty    213.109.202.127  Tue Oct  1 11:03 - 11:03  (00:00)
    udatabas ssh:notty    139.19.117.130   Tue Oct  1 10:34 - 10:34  (00:00)
    Admin    ssh:notty    213.109.202.127  Tue Oct  1 09:58 - 09:58  (00:00)
             ssh:notty    79.110.62.93     Tue Oct  1 09:40 - 09:40  (00:00)
    udatabas ssh:notty    139.19.117.130   Tue Oct  1 09:34 - 09:34  (00:00)
    

    Uma abordagem geral:

    • precisamos determinar se devemos imprimir campos 5,6,7,3ou campos4,5,6,2
    • 5,6,7,3é a mesma coisa que(5-0),(6-0),(7-0),(3-0)
    • 4,5,6,2é a mesma coisa que(5-1),(6-1),(7-1),(3-1)
    • podemos generalizar isso para (5-offset),(6-offset),(7-offset),(3-offset)onde offsetestá 0ou1
    • podemos testar atributos do 1º campo para determinar o valor deoffset

    Algumas awkideias baseadas em diferentes atributos do 1º campo:

    ########
    # determine offset by contents of 1st field
    
    awk '
    { offset = ( $1 ~ /ssh:/ ) ? 1 : 0                       # if 1st field contains string "ssh:" then offset = 1, else offset = 0
      print $(5-offset),$(6-offset),$(7-offset),$(3-offset)  # apply offset to determine which fields to print
    }'
    
    ########
    # determine offset by position of 1st field in the line
    
    awk '
    { offset = ( index($0,$1) != 1 ) ? 1 : 0                 # if 1st field does not start in column 1 then offset = 1, else offset = 0
      print $(5-offset),$(6-offset),$(7-offset),$(3-offset)
    }'
    

    Outra abordagem seria inserir um campo 'espaço reservado' no início da linha quando o primeiro campo estiver 'ausente'.

    Uma awkideia usando o index($0,$1)atributo:

    awk '
    { $1 = (index($0,$1)==1 ? "" : "placeholder" FS) $1    # if 1st field starts in column 1 then no placeholder is needed otherwise prepend the 1st field with the string "placeholder" 
      $0=$0                                                # force awk to reparse the new line; since all lines now have the same number of fields ...
      print $5,$6,$7,$3                                    # there's no need for an offset
    }'
    

    Removendo comentários, reduzindo-os a uma linha e lendo lastba saída do stdin:

    cat lastb.out | awk '{offset = ($1~/ssh:/) ? 1 : 0; print $(5-offset),$(6-offset),$(7-offset),$(3-offset)}'
    
    cat lastb.out | awk '{offset = (index($0,$1)!=1) ? 1 : 0; print $(5-offset),$(6-offset),$(7-offset),$(3-offset)}'
    
    cat lastb.out | awk '{$1 = (index($0,$1)==1 ? "" : "placeholder" FS) $1; $0=$0; print $5,$6,$7,$3}'
    

    Todos eles geram:

    Oct 1 12:07 213.109.202.127
    Oct 1 11:48 8.219.222.66
    Oct 1 11:03 213.109.202.127
    Oct 1 10:34 139.19.117.130
    Oct 1 09:58 213.109.202.127
    Oct 1 09:40 79.110.62.93
    Oct 1 09:34 139.19.117.130
    

    Em vez de testar atributos do 1º campo, você poderia (pelo menos para os dados de amostra que nos foram fornecidos) testar o número de campos ( NF):

    • NF==9==> 9 campos: estamos 'faltando' o 1º campo, então colocamos offset=1ou prefixamos placeholderno início da linha
    • NF==10==> 10 campos: não definimos offset=0ou acrescentamos nada no início da linha
    • 0
  5. ilkkachu
    2024-11-11T02:54:51+08:002024-11-11T02:54:51+08:00

    Esse formato de saída parece ter um número fixo de caracteres por campo, para que possamos escolher as partes corretas com, por exemplo, substr()a função do AWK.

    Com lastba entrega dessa saída específica:

    % lastb | awk '{printf "%s %s\n", substr($0, 44, 12), substr($0, 23, 15) }'
    Oct  1 12:07 213.109.202.127
    Oct  1 11:48 8.219.222.66
    Oct  1 11:03 213.109.202.127
    ...
    

    Ou o mesmo com GNU AWK eFIELDWIDTHS :

    % lastb | gawk -v FIELDWIDTHS="22:15 6:12"  '{ print $2,$1 }'
    Oct  1 12:07 213.109.202.127
    Oct  1 11:48 8.219.222.66
    Oct  1 11:03 213.109.202.127
    ...
    

    O primeiro número antes dos dois pontos é o número de colunas a ignorar, o segundo é o número de colunas a incluir neste campo. Claro, você pode especificar larguras para todos os campos e usar apenas os que precisa, eu apenas ignorei preguiçosamente tudo, exceto as partes que queremos.

    O procedimento acima obviamente falhará se alguns valores fizerem com que as colunas fiquem desalinhadas (por exemplo, nomes de usuários muito longos, datas aparecendo em um formato diferente, etc.).

    • 0

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve