Como clonar uma parte somente leitura do sistema de arquivos / proc

1

O problema com o sistema de arquivos de leitura / proc é que ele não é atômico. Eu tentei usar uma biblioteca (procfs em Python) que deseja lê-lo, mas tem falhas de cerca de 5% do tempo, porque o processo que estou depois já passou. Então, desejo copiar tudo em / proc para outro local, digamos /proc_clone/<GUID>/ . Um GUID pode ser gerado usando o comando uuidgen .

A abordagem ingênua seria tentar usar cp -r , mas estou recebendo muitos erros de 'permissão negada' e isso leva mais de um segundo. Eu sou apenas após um subconjunto /proc/<pid> e, mesmo assim, apenas o material somente leitura que pode ser transformado em uma string (em última análise, desejo construir um único arquivo JSON que contenha tudo isso).

Eu estou procurando um script que faça isso para mim e também seja curto, simples, muito rápido, pode lidar com processos que morrem no meio do caminho pulando-os , no entanto, eu gostaria de evite escrever código C - eu preferiria muito mais a bash, utilitários existentes e talvez Perl / Python. O objetivo aqui é apenas tirar um instantâneo de um subconjunto de /proc , não produzir o próprio arquivo JSON.

Eu ouvi opiniões de que "ninguém deve tentar copiar /proc , mas apenas ler a partir dele". Bem, a natureza não atômica significa que é preciso lançar um monte de try/catch em todo o código ao tentar fazer operações muito simples. Usar uma linguagem de alto nível como o Python (o que eu quero usar no final das contas) para iterar sobre /proc é um método lento, que envolve o tempo de IO e de CPU. Isso aumenta o risco de ver um processo morrer em você (eu certamente o vejo com frequência; tenho um script que interroga / proc cada minuto e tenho muitas exceções). Eu gostaria de construir uma biblioteca que produza um único arquivo JSON que contenha cpu e informações de uso de memória sobre processos em um formato legível (por exemplo, usando segundos e não jiffies, bytes e não páginas, ter unidades além de valores. Não estou preocupado que levaria algum tempo para criar esse arquivo fora de um despejo de diretório, eu só quero ter certeza de que o instantâneo é tão preciso quanto possível.Então, se eu não deveria apenas copiar / proc over, então qual outro método deve Eu uso?

    
por Leonid 27.04.2013 / 01:29

1 resposta

2

Você precisa dar uma olhada nas páginas man do proc . Veja /proc/[pid]/* entradas e escolha quais arquivos você deseja.

Você não quer copiar tudo. Como exemplo você tem /proc/[pid]/mem , que é toda a memória virtual para um processo incluindo compartilhado etc. - ou seja, o tamanho de toda a sua memória. Além disso, você não poderá lê-lo, a menos que o processo tenha mem ou seja ptraced e lido com privilégios mais altos. (E então somente Tamanho Virtual - /proc/pid/status -> VmSize ) - e assim por diante.

Ou /proc/PID/exe , que é simplesmente um link para o executável, /proc/PID/fd/* , que contém descritores de arquivo para stdin , stdout , stderr e outros arquivos, tubos etc.

Também há muitos outros arquivos especiais , e muitos links (se você seguir todos eles, nunca será feito). Leia o homem mencionado acima, documentação do kernel.org , etc.

Além disso, os arquivos não são arquivos de dispositivo de bloco. Eles residem na memória como proc é um sistema de arquivos baseado em memória. De certa forma, você pode chamar isso de janela para o kernel organizados para facilitar o acesso.

Assim, esta é também uma grande vantagem quando se trata das leituras parece que você quer - como a informação reside na memória não há nenhum disco I / O e, portanto, muito rápido. Claro, se você escolher gravar os dados no disco, isso é perdido - mas ainda é muito mais rápido do que disco para disco.

Olhe como memória compartilhada e tente não duplicar mais do que o necessário. Para sua tarefa, você provavelmente também veria arquivos no nível raiz de %código%. Veja o código-fonte para /proc , ps , top etc. para obter uma rápida introdução de como outras ferramentas o fazem.

Escrevi algumas outras respostas que podem mais ou menos tocar alguns dos aspectos. Você pode achar útil:

Editar:

Quanto ao comentário. Você poderia fazer algo como:

save_to=/some/path

pushd /proc
for d in [0-9]*; do
    cp "$d/cmdline" "$save_to/$d.cmdline"
    cp "$d/status" "$save_to/$d.status"
done
popd

Mas eu teria usado algum nível inferior como, por exemplo, C para analisar os arquivos como o método acima bastante possível não seria rápido o suficiente para o que se deseja.

Se for uma cópia única a cada hora, OK, mas não para, por exemplo, segundos ou até intervalo de alguns minutos.

    
por 27.04.2013 / 03:07