Considere ler as informações necessárias diretamente do sistema de arquivos /proc
em vez de usar uma ferramenta como ps
. Você encontrará as informações que está procurando ("args") dentro do arquivo /proc/$pid/cmdline
, separadas apenas por bytes NUL em vez de espaços.
Você pode usar este sed
one-liner para obter os argumentos do processo $pid
:
sed -e 's/\x00\?$/\n/' -e 's/\x00/ /g' "/proc/$pid/cmdline"
Este comando é equivalente a:
ps -o args= -p "$pid"
(Usar args=
em ps
omitirá o cabeçalho.)
O comando sed
primeiro procurará pelo último byte NUL à direita e o substituirá por uma nova linha, e depois substituirá todos os outros bytes NUL (separando argumentos individuais) por espaços, finalmente produzindo o mesmo formato que você está vendo ps
.
Com relação aos processos de catalogação no sistema, ps
faz isso listando os diretórios em /proc
, mas há condições de corrida inerentes a esse procedimento, já que os processos estão iniciando e saindo enquanto ps
está em execução. não é realmente um instantâneo, mas uma aproximação. Em particular, é possível que ps
mostre processos que já foram finalizados no momento em que mostra seus resultados, ou omite processos que foram iniciados enquanto estava em execução (mas não foram retornados pelo kernel enquanto listavam o conteúdo de /proc
.)
Eu sempre assumi que se um processo está lá antes que ps
comece e ainda esteja lá depois que terminar, então não será omitido por ele, eu < em> assumido o kernel garantiria que estes seriam sempre incluídos, mesmo que haja muitos processos sendo criados e destruídos. O que você está descrevendo implica que não é o caso. Eu ainda estou cético sobre isso, mas dado que existem condições de corrida conhecidas em como ps
funciona, eu acho que é pelo menos plausível que listar PIDs de /proc
pode perder um existente devido a essas condições de corrida.
Seria possível verificar isso verificando a origem do kernel do Linux, mas eu não fiz isso (ainda), então realmente não posso dizer com certeza se existe uma condição de corrida desse tipo que perderia uma corrida longa processo, como você descreve.
A outra parte é a maneira como ps
funciona. Mesmo que você esteja passando um único PID com o argumento -p
, ele ainda está listando todos os PIDs existentes, mesmo que você esteja interessado apenas nesse único. Poderia ter um atalho nesse caso e pular listando as entradas em /proc
e indo diretamente para /proc/$pid
.
Eu não posso dizer por que isso foi implementado dessa maneira. Talvez porque a maioria das opções ps
sejam "filtros" nos processos, então implementar -p
da mesma maneira foi mais fácil, usar um atalho para ir direto para /proc/$pid
pode envolver um caminho de código separado ou duplicação de código ... Outra hipótese é que alguns casos, incluindo -p
mais opções adicionais, acabariam exigindo listagem, por isso talvez seja complexo determinar quais casos exatos permitiriam usar o atalho e quais não permitiriam.
O que nos leva à solução alternativa, indo diretamente para /proc/$pid
, sem listar o conjunto completo de PIDs do sistema, evitando todas as raças conhecidas e simplesmente obtendo as informações que você precisa diretamente da fonte.
É um pouco feio, mas o problema descrito realmente existe, deve ser uma maneira confiável de buscar essas informações.