Disputando sed para encontrar e reformatar a data de login (ou, como matar processos mosh-server ociosos)

1

Eu tenho um método antigo de matar processos mosh-idle idle, o que não funciona no meu novo VPS.

Aqui está o método antigo, que eu executo no crontab do root para limpar os processos que estão inativos por mais de 10 dias:

for tty in 'w -sf | grep -P '\d\ddays mosh-server' | cut -c 10-15'; do kill -9 'ps -o pid= -t $tty'; done

O problema é que no novo VPS, esses processos não têm TTYs, então eu não posso combinar com TTY e matar mosh dessa maneira. Aqui está o que eu tenho até agora (BTW, o novo VPS está rodando o kernel 3.2 no Debian wheezy, o antigo era a edição Debian anterior).

for loginday in 'w | grep -P '\d\ddays.* mosh-server' | cut -c 34-40 | sed 's/^\([0-9]*\)\([a-zA-Z]*\).*$/ /''; do echo $loginday; done

Estou tentando obter o dia de login de 'w' e correlacioná-lo mais tarde com as informações de 'ps':

ps -C mosh-server -o bsdstart

Assim, eu poderia correlacionar quaisquer sessões mosh-server ociosas iniciadas no mesmo dia que o login (que provavelmente é 99,9% delas em estado selvagem) e matá-las dessa forma, usando 'ps' para obter o pid.

No entanto, 'w' gera o dia de login assim:

03Oct13

Que eu cortei para simplesmente "03Oct".

E as saídas 'ps' assim:

Oct 3

Você pode ver no comando sed acima, que é a parte que não está funcionando, estou tentando obter "03Oct" e a saída "Oct 03" (vou lidar com os zeros quando obtiver esse trabalhando) e eu não posso para a vida de eu conseguir sed para trabalhar dentro do loop for quando parece funcionar quando eu testo com 'echo':

echo 03Oct | sed 's/\([0-9]*\)\([a-zA-Z]*\).*/ /'

O que está atrapalhando o comando sed depois de colar no loop for?

Melhor ainda, existe uma maneira melhor ou menos hacky de fazer isso? Considerando que os processos mosh-server ociosos e desanexados não possuem TTYs no Linux 3.2 que eu possa associar facilmente? Edit: Além disso, em sistemas com libutempter instalado, mosh-server irá escrever informações para o utmp que eu suspeito que seriam úteis, mas eu não sei como chegar a ele.

    
por Gordon Morehouse 16.11.2013 / 20:22

2 respostas

1

Seu teste echo é diferente do seu teste de loop de duas maneiras significativas:

  • Não há espaço em branco em torno da data
  • a regex carece de âncoras

Parte do motivo pelo qual o teste de loop não está funcionando é que você não está levando em conta o espaço em branco. Outra razão é que você está usando o quantificador * , que significa "zero ou mais" e tem o efeito que você quer alguns dígitos, mas não realmente. Para corrigir isso, você poderia usar o quantificador + , que significa "um ou mais". Nós vamos usar isso para os caracteres alfa. No entanto, como você deseja eliminar o zero inicial, podemos seguir um pouco a direção diferente com os dígitos.

Como o GNU sed suporta regexes estendidas, podemos eliminar o escape de todos os caracteres especiais, além daqueles que adicionamos. Observe, no entanto, que a opção -r não é portátil. Além disso, estou substituindo a classe de caracteres nomeada por caracteres alfabéticos para tornar a regex um pouco mais legível e torná-la compatível com idiomas com conjuntos de caracteres diferentes.

sed -r 's/^ *((0)|([1-9]))([0-9])([[:alpha:]]+).*$/ /'

O zero inicial está sendo capturado no grupo 2 e está sendo descartado. Grupo 1 é o dígito principal do número de dois dígitos. Grupo 3 está vazio quando o grupo 2 contém um zero (por causa da alternância criada usando o caractere de pipe).

No que diz respeito a utmp , last mosh-server produz nada útil para você (com o libutempter instalado)?

Consulte também Gerenciamento de processos para ver se você encontrou algo útil.

    
por 17.11.2013 / 03:23
1

Para fazer algo um pouco mais preciso do que as datas de análise, você pode olhar o sistema de arquivos / proc. Algo assim funciona para mim no redhat:

⚡ for pid in $(pgrep mosh-server -u $USER); do if [[ $(stat -c %Y /proc/$pid) -lt $(( $(date +%s) - 36000 )) ]]; then echo "$pid is probably stale";fi;  done
27831 is probably stale                                                                                                                                      
38041 is probably stale                                                                                                                                      
38669 is probably stale                                                                                                                                      

⚡ ps fux | grep mosh                                                                                                                                         
1524      2444  0.4  0.0 160352  4752 ?        S    08:27   0:00 mosh-server new -c 256 -s -l LANG=en_US.UTF-8 -- bash -lc use prod                          
1524     27831  0.0  0.0 161648  6288 ?        S    Apr05   0:02 mosh-server new -c 256 -s -l LANG=en_US.UTF-8 -- bash -lc use prod                          
1524     38041  0.0  0.0 159696  4332 ?        S    Apr04   0:03 mosh-server new -c 256 -s -l LANG=en_US.UTF-8 -- bash -lc use prod                          
1524     38669  0.0  0.0 161276  5920 ?        S    Apr04   0:37 mosh-server new -c 256 -s -l LANG=en_US.UTF-8 -- bash -lc use prod 

Altere o eco para kill e o 36000 para o que você quiser que seu tempo limite em segundos seja. Se você quiser fazer isso para todos os usuários, solte o -u $ USER e execute-o como root.

    
por 06.04.2018 / 14:30