Quero executar um processo que gere filhos, por exemplo,
for i in {1..4}; do
sh -c 'echo $$; for j in {1..3}; do
sh -c "echo ...\$\$; sleep 1"
done'
done
e gostaria de monitorar o uso da CPU e da memória a cada 2 segundos com o top
.
- Posso monitorar o uso de recursos com
top -p <PID>
, mas isso não leva em conta os filhos. - Posso monitorar todos os processos em execução apenas com
top
, mas isso é muita informação. - Posso pré-calcular uma lista de PIDs e depois passar todos eles para
top
, mas o processo poderia então gerar novos filhos, que não seriam contabilizados.
Como posso obter um top
instantâneo a cada 2 segundos apenas do processo que estou executando e de todos os processos que ele gera?
Alguém fez uma pergunta parecida aqui , mas tratava-se de resumir essas informações em um único número, após o término do processo. Minha pergunta é sobre monitorar continuamente os processos enquanto eles ainda estão em andamento.
Já que você mencionou em um comentário que geralmente seria viável preparar algo antes de lançar o processo mãe, e porque seu exemplo lança um contêiner, que provavelmente já faz isso:
Basta usar cgroups Linux para monitorar (e se desejar, controlar e limitar) os recursos usados pelo seu grupo de processos relacionados.
É bem simples: se o seu processo estiver em um cgroup, então seus filhos serão gerados no mesmo. Então, coloque seu processo mãe em um cgroup próprio (que é "basicamente gratuito", por padrão um novo cgroup herda tudo do cgroup pai). Em seguida, pesquise regularmente os processos nesse cgroup a partir dos controladores cgroupsv2 e exiba-os. O jogo inteiro fica assim:
Salve isso em um arquivo, torne o arquivo executável (
chmod 755 filename
) e execute-o com o PID do processo pai (/path/to/filename 1234
).Isso quase certamente funcionará com qualquer coisa que já seja um contêiner (por exemplo, contêineres flatpak, podman e docker, contêineres apptainer,…).
É super fácil começar algo em um cgroup próprio:
(claro, se o programa for realmente um serviço, remova
--scope
e execute como serviço; se for para ser executado como sistema, não como programa de usuário, remova o--user
. Idealmente, se for um serviço, você ' d apenas escrever as 6 linhas de configuração para torná-lo um serviço systemd completo com seu próprio escopo)Há uma série de opções.
TTY=pts/*number*
. Observe que você precisará ativar a exibição do TTY. Inicia-se esta filtragem pressionandoo
ou usandoO
para adicionar outro filtro. Você pode isolar um comando para ser a única coisa em um tty com vários comandos, incluindoscreen command
andxterm -e command
, andssh -t localhost command
(que também tem a vantagem de não perder a saída).V
e, em seguida, fechar os nós pais indesejados comv
. Isso deve permitir que você o restrinja o suficiente apenas para ver seu comando, embora possa levar algum tempo para restringi-lo. Talvez seja necessário combinar isso com outras coisas, já que normalmente há apenas uma ou duas árvores completas.u
.Essas técnicas, ou uma combinação delas, podem fornecer os resultados desejados.
Editar: para facilitar a configuração, você pode querer escrever algo como
tty;sleep 10
no topo do seu script... ou mesmo em outro script queexec
seja o seu script de destino.Se você não se importa em executar seu programa em um namespace de usuário diferente usando
unshare
, poderá filtrartop
de acordo com o namespace do usuário.Você também executa
unshare -r <COMMAND>
e procura o namespace do usuário com o pid.Agora, para visualizar todos os processos no namespace do usuário em
top
:Pressione
f
para escolher um campoUsando as teclas de seta Down/ Up, navegue até
nsUSER
(USER namespace Inode).Ative-o pressionando a tecla de espaço
Pressione “q” para voltar à
top
visualização principal.Pressione “O” para acionar o filtro e filtrar os processos de acordo com o namespace do usuário
Feito.
O que eu criei para minha própria pergunta não é tão legal quanto as outras pessoas postaram:
Em seguida, a execução
monitor_with_top <my_PID> 2
imprime a tela superior esperada a cada 2 segundos.( Editar: ah, certo, como o aviro apontou,
top
só funcionará com até 20 PIDs passados dessa maneira. Seguindo a resposta de Marcus Müller, você pode usarhtop
with--tree --readonly
em vez disso.)Como também queria um recurso semelhante, escrevi um script que faz isso.
A vantagem do script é que ele
top
roda continuamente, então ele realmente mostra o consumo de CPU do último intervalo (3 segundos por padrão, mas pode ser alterado com o-d secs
parâmetro).As respostas anteriores rodavam
top
uma vez a cada ciclo, e nesse casotop
mostra apenas o consumo de CPU naquele exato momento. A média de 3 segundos é mais precisa.Também resolve o problema de
top
não conseguir receber mais de 20 pids.Este script requer configuração
top
no "Modo Forest View" 1 : Você precisará iniciartop
, pressionarV
para alternar o modo florestal e depois pressionarW
para gravar sua configuração atual em seu$HOME/.toprc
arquivo de configuração 2 .O script 3 é executado
top
continuamente (por padrão), com todo o processo em execução no host, e faz algumas análisessed
para apresentar apenas o pid necessário e seus filhos.Aqui está o código. Não fiz nenhum teste sério e não me preocupei em pensar em casos extremos, apenas fiz funcionar. Talvez eu melhore isso no futuro.
Exemplo:
Observe que você pode adicionar qualquer sinalizador ao script que seria passado para
top
. Por exemplo, se você quiser ver as linhas de comando completas, adicione-c
:1 Gostaria que
top
houvesse mais opções de linha de comando, que permitissem iniciar o modo de visualização da floresta a partir da linha de comando sem ter que alterar a visualização padrão, mas é o que é.2 Ao emitir o comando 'W' logo antes de sair do topo, você poderá reiniciar mais tarde exatamente no mesmo estado
3 Poderia ter sido mais elegante fazer isso em python, mas tudo bem.