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) lastb
fica 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!
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:Usando
awk
:Em
awk
, o valor padrão deFS
é 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:
Aqui,
FS
(conforme definido com a-F
opção) being[[:blank:]]+
, significa que qualquer sequência de um ou mais espaços em branco constitui um separadorF
de campoS
, incluindo aqueles no início da linha. Se uma linha começa com um espaço em branco, isso significa que$1
será 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' localhost
e alastb
saída terá:(veja também aquela tentativa genuína fracassada onde o terceiro campo
login screen
conté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 porsshd
, ou as primeiras linhas do nome de usuário para aqueles nomes de usuário que contêm novas linhas.Para sua informação, o
lastb
utilitário já foi removido do Debian desde maio de 2024 (o que me parece prematuro, já que a maioria das coisas ainda registra entradas emwtmp
/btmp
e poucas coisas ainda emwtmpdb
; 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 aNEWS
entrada relacionada noutil-linux
pacote Debian:(você também precisa instalar o que é recomendado
libpam-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
journalctl
poderia ser algo como:Ou para alguma saída JSON para facilitar o pós-processamento:
O que dá algo como:
(também usado
_SOURCE_REALTIME_TIMESTAMP
para obter o horário em que o evento foi gerado, em vez de recebido).Onde você vê minhas tentativas anteriores de enganar
lastb
sendo tratadas de uma forma mais útil do que porlastb
, até mesmolastb --time-format=iso -w
.¹ por POSIX, isso é nova linha ou qualquer caractere para o qual
iswblank()
retorna verdadeiro, mas você descobrirá em algumasawk
implementações, que é qualquer caractere para o qualiswspace()
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=iso
para obter esse formato comlastb
precisão de subsegundos, embora sem ela.Para simular
lastb
a chamada do OP:Uma abordagem geral:
5,6,7,3
ou 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)
(5-offset),(6-offset),(7-offset),(3-offset)
ondeoffset
está0
ou1
offset
Algumas
awk
ideias baseadas em diferentes atributos do 1º campo:Outra abordagem seria inserir um campo 'espaço reservado' no início da linha quando o primeiro campo estiver 'ausente'.
Uma
awk
ideia usando oindex($0,$1)
atributo:Removendo comentários, reduzindo-os a uma linha e lendo
lastb
a saída do stdin:Todos eles geram:
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 colocamosoffset=1
ou prefixamosplaceholder
no início da linhaNF==10
==> 10 campos: não definimosoffset=0
ou acrescentamos nada no início da linhaEsse 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
lastb
a entrega dessa saída específica:Ou o mesmo com GNU AWK e
FIELDWIDTHS
: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.).