Eu deparei com um problema estranho no qual um ps -o args -p <pid>
comando falha ocasionalmente ao encontrar o processo em questão, mesmo que esteja definitivamente em execução no servidor em questão. Os processos em questão são scripts de wrapper de longa execução usados para iniciar alguns aplicativos Java.
As ocorrências "in the wild" da questão sempre parece acontecer no início da manhã, para que haja alguma evidência de que ele está relacionado à carga em disco no servidor em questão, porque eles estão muito fortemente carregado então, mas executando o ps
em pergunta em um loop apertado, eu posso eventualmente replicar o problema - uma vez a cada poucas centenas de vezes que eu recebo um erro.
Ao executar o seguinte script bash, eu consegui gerar uma saída de rastreio para uma execução com falha e com êxito:
while [ $? == 0 ] ; do strace -o fail.out ps -o args -p <pid> >/dev/null ; done ; strace -o good.out ps -o args -p <pid>
Comparando a saída de fail.out
e good.out
, posso ver que a getdents
chamada do sistema na execução que falha de alguma forma retorna um número muito menor do que a contagem real de processos no sistema (da ordem de ~ 500 em comparação com ~ 1100)
grep getdents good.out
getdents(5, /* 1174 entries */, 32768) = 32760
getdents(5, /* 31 entries */, 32768) = 992
getdents(5, /* 0 entries */, 32768) = 0
grep getdents fail.out
getdents(5, /* 673 entries */, 32768) = 16728
getdents(5, /* 0 entries */, 32768) = 0
... e essa lista mais curta não inclui o pid real em questão, portanto não foi encontrado.
Você pode ignorar esta seção, os erros ENOTTY são explicados pelo comentário de dave_thompson abaixo e não são relacionados
Além disso, a execução com falha obtém alguns
ENOTTY
erros que não aparecem na execução bem-sucedida. Perto do início da saída, vejoioctl (1, TIOCGWINSZ, 0x7fffe19db310) = -1 ENOTTY (ioctl inadequado para o dispositivo) ioctl (1, TCGETS, 0x7fffe19db280) = -1 ENOTTY (ioctl inadequado para o dispositivo)
E no final, vejo um único
ioctl (1, TCGETS, 0x7fffe19db0d0) = -1 ENOTTY (ioctl inadequado para o dispositivo)
A falha
ioctl
no final ocorre logo antes dosps
retornos, mas ocorre após ops
já ter imprimido um conjunto de resultados vazio, portanto, não tenho certeza se eles estão relacionados. Eu sei que eles são consistentes em todas as saídas strace com falha que tenho, mas não aparecem nas que foram bem-sucedidas.
Não tenho absolutamente nenhuma idéia de por getdents
que ocasionalmente não encontraria a lista completa de processos, e agora cheguei ao ponto em que vou dar um tapa-band na coisa toda, alterando o script de controle que verifica o script do wrapper em questão para ligar pela ps
segunda vez se o primeiro falhar, mas eu estaria interessado em saber se alguém tem alguma idéia do que está acontecendo aqui.
O sistema em questão está executando o Kernel 4.16.13-1.el7.elrepo.x86_64 no CentOS 7 e procps-ng versão 3.3.10-17.el7_5.2.x86_64
>/dev/null
na invocação 'falha' (no circuito), mas não o 'bom' invocação, daí o ENOTTY em fd 1.Respostas:
Considere ler as informações necessárias diretamente do
/proc
sistema de arquivos e não através de uma ferramenta comops
. Você encontrará as informações que procura ("args") dentro do arquivo/proc/$pid/cmdline
, separadas apenas por NUL bytes, em vez de espaços.Você pode usar esta linha
sed
única para obter os argumentos do processo$pid
:Este comando é equivalente a:
(Usar
args=
emps
omitirá o cabeçalho.)O
sed
comando primeiro procurará o último byte NUL à direita e o substituirá por uma nova linha; depois disso, substituirá todos os outros bytes NUL (separando argumentos individuais) por espaços, produzindo finalmente o mesmo formato do qual você está vendops
.Em relação aos processos de listagem no sistema,
ps
faça-o listando diretórios/proc
, mas existem condições de corrida inerentes a esse procedimento, uma vez que os processos estão iniciando e saindo enquantops
está em execução; portanto, o que você obtém não é realmente um instantâneo, mas uma aproximação. Em particular, é possível queps
mostre processos que já foram finalizados no momento em que mostra seus resultados ou omita processos iniciados enquanto estava em execução (mas não foram retornados pelo kernel ao listar o conteúdo de/proc
.)Eu sempre assumi que, se um processo existe antes do
ps
início e ainda existe após a conclusão, não seria esquecido, assumi que o kernel garantiria que eles sempre fossem incluídos, mesmo que haja muitos outros processos. sendo criado e destruído. O que você está descrevendo implica que não é esse o caso. Ainda estou cético quanto a isso, mas, como existem condições de corrida conhecidas em comops
funciona, acho que é pelo menos plausível que listar PIDs/proc
possa perder uma existente devido a essas condições de corrida.Seria possível verificar isso verificando a fonte do kernel do Linux, mas ainda não o fiz (ainda), então não posso realmente ter certeza se existe uma condição de corrida que perderia um processo de longa execução, como você descreve.
A outra parte é a maneira como
ps
funciona. Mesmo se você estiver passando um único PID com o-p
argumento, ele ainda está listando todos os PIDs existentes, mesmo que você esteja interessado apenas nesse único. Definitivamente, poderia pegar um atalho nesse caso e pular a lista das entradas/proc
e ir diretamente para/proc/$pid
.Não sei dizer por que foi implementado dessa maneira. Talvez porque a maioria das
ps
opções seja "filtros" nos processos, a implementação-p
da mesma maneira fosse mais fácil, usando um atalho para ir direto para/proc/$pid
envolver um caminho de código separado ou duplicação de código ... Outra hipótese é que alguns casos, incluindo-p
opções adicionais, seriam acabam exigindo listagem, por isso talvez seja complexo determinar quais casos exatos permitiriam o atalho e quais não.O que nos leva à solução alternativa, indo direto para
/proc/$pid
, sem listar o conjunto completo de PIDs do sistema, evitando todas as corridas conhecidas e simplesmente obtendo as informações necessárias diretamente da fonte.É um pouco feio, mas o problema que você descreve realmente existe, deve ser uma maneira confiável de obter essas informações.
fonte