parse a saída de um comando para mostrar apenas linhas com base no intervalo de dados de uma coluna específica

3

Este é certamente um caso de rtfm, já que eu me deparei com muitos posts similares, mas estou me perdendo em tentar encontrar o que estou procurando. Eu imagino que awk ou grep será capaz de ajudar de alguma forma, eu poderia usar alguma ajuda para me apontar na direção certa.

Eu tenho um plano futuro de escrever um script com prompts que outro usuário pode executar para essa função, mas primeiro quero ter a idéia básica para trabalhar por mim mesmo.

Eu preciso usar who -u para exibir os usuários atualmente conectados e, com base na hora em que estão inativos, exibir o ID do usuário, o tempo ocioso e o pid.

Por exemplo,

01sale1  pts/11       2016-10-05 06:39 00:04       14132 (192.168...)
01sale2  pts/16       2016-10-05 06:40 00:07       17902 (192.168...)
01sale3  pts/14       2016-10-05 06:40   .         17779 (192.168...)
01sale5  pts/25       2016-10-05 06:41 00:04       18339 (192.168...)

A lista é bastante longa quando todos estão ativos e estamos enfrentando problemas que atingem o limite de licenças para esse software específico. Até que isso seja resolvido, eu preciso chutar os usuários ociosos por mais ou menos uma hora.

O que eu gostaria é de executar quem -u para mostrar apenas as colunas 1, 5 e 6 com base em se a coluna 6 é mais de uma hora, por isso, seria 01: ** ou acima.

Eventualmente, quero criar um script que um usuário sem privilégios de root possa executar para mostrar essas informações e depois matar usuários inativos. Eu não tenho certeza se eu quero isso totalmente automatizado ou ainda não embora.

Estou executando este aplicativo em um Red Hat mais antigo

    
por Mike D 05.10.2016 / 14:36

2 respostas

0

O tempo inativo é derivado do último horário de acesso do dispositivo tty, portanto, você poderia fazer:

kill_idle() (
  sig=$1
  old_ttys=$(find /dev/pts -type c ! -name ptmx -amin +60 -printf %p,)
  [ "$#" -eq 0 ] || pkill "-$sig" -t "$old_ttys"
)
kill_idle HUP; sleep 3; kill_idle KILL

Para matar todos os processos controlados por aqueles ttys inativos.

Agora, conforme apontado corretamente pelo @rudimeter, /dev/pts dispositivos nem sempre são usados apenas para sessões de terminal de usuário, portanto, podemos acabar com processos de eliminação que usam pseudo-terminais para outros propósitos (como expect , socat ou pty usando outras disciplinas de terminal).

Coisas como emuladores de terminal, getty, screen, sshd registram os pseudo-terminais que eles geram no banco de dados utmp , que é o que who -u consulta.

Para obter os terminais ociosos da saída de who -u , você poderia fazer:

old_ttys=$(
  who -u | awk '$5 != "." && $5 !~ /^00/ {printf "%s,", $2}'
)

Observe, entretanto, que a saída de who -u pode ser adulterada em sistemas que usam utempter para registrar o arquivo.

Por exemplo, aqui usando socat para criar o pty:

name=$':0)\nnobody pts/2 2016-10-05 00:00 old 123 (:0' socat pty \
  system:'/usr/lib/x86_64-linux-gnu/utempter/utempter add \"$name\"; sleep infinity',nofork &

utempter é um comando sgid que adiciona a entrada em utmp. Ele valida sua entrada até certo ponto, já que em seu stdin tem que apontar para ptmx e os pts correspondentes devem ser de propriedade do responsável pela chamada, mas ele não valida o campo host . Aqui, especificando um campo host com um caractere de nova linha, estamos fazendo uma entrada falsa na saída de who -u :

nobody pts/2 2016-10-05 00:00 old 123 (:0)

Isso significa que você pode matar os processos em qualquer pts.

Para listar apenas os terminais inativos:

who -u | awk '$5 != "." && $5 !~ /^00/'

Ou apenas para listar o usuário, o tempo ocioso e o pid do processo de controle do terminal:

who -u | awk '
  $5 != "." && $5 !~ /^00/ {printf "%-16s %6s %d\n", $1, $5, $6}'

O comando w pode fornecer uma saída mais útil (também não é vulnerável ao exploit mencionado acima):

$ w -sf | awk 'NR > 2 && $3 !~ /[0-9]s?$/'
stephane tty7      50days /usr/bin/lxsession -s LXDE -e LXDE
stephane pts/1      3:07m /bin/zsh
stephane pts/3      1:25m elinks
    
por 05.10.2016 / 15:04
2

Você pode tentar algo assim:

who -u | \
awk '$5 ~ /^[0-9][1-9]:.*$|^[1-9][0-9]:.*$/ {printf "%s %s %s\n", $1,$5,$6}'  

awk corresponde a padrões que começam com 0[1-9] || [1-9][0-9] .
Você pode tentar combinar padrões não iniciados com 00 , se desejar.

    
por 05.10.2016 / 14:55