web-dev-qa-db-ja.com

/ procファイルシステムの読み取り専用部分のクローンを作成する方法

/ procファイルシステムの読み取りに関する問題は、それがアトミックではないことです。読みたいライブラリ(Pythonのprocfs)を使ってみましたが、後のプロセスがなくなったため、5%程度の確率でグリッチが発生します。したがって、/ proc内のすべてを別の場所(/proc_clone/<GUID>/など)にコピーしたいと思います。 GUIDは、uuidgenコマンドを使用して生成できます。

素朴なアプローチはcp -rを使おうとしますが、「許可が拒否されました」というエラーが大量に発生し、1秒以上かかります。私はサブセット/proc/<pid>の後で、それでも文字列に変換できる読み取り専用のものだけを探しています(最終的には、これらすべてを含む単一のJSONファイルを作成したいと思います)。

私はそれを実行し、短く、シンプルで、非常に高速なスクリプトを探しています飛行中に終了するプロセスをスキップすることで処理できますただし、Cを記述しないようにしますコード-私はむしろbash、既存のユーティリティ、そして多分Perl/Pythonに固執したいと思います。ここでの目標は、JSONファイル自体を生成するのではなく、/procのサブセットのスナップショットを取得することです。

/procをコピーするのではなく、そこから読むだけでいい」という意見を聞いたことがあります。さて、それの非アトミックな性質は、非常に単純な操作を行おうとすると、コード全体にtry/catchの束を投げなければならないことを意味します。 Python(私が最終的に使用したいもの)のような高水準言語を使用して/procを反復処理するのは遅い方法であり、IOこれにより、プロセスが停止するリスクが高まります(確かによく見られます。毎分、/ procに問い合わせるスクリプトがあり、多くの例外が発生します)。出力するライブラリを構築したいと思います。プロセスに関するCPUとメモリ使用量の情報を人間が読み取れる形式で含む単一のJSONファイル(たとえば、秒を使用し、Pythonを使用せず、バイトを使用し、ページを使用しない場合、値に加えて単位があります。時間がかかることは心配していません。ディレクトリダンプからそのファイルを作成します。スナップショットができるだけ正確であることを確認したいだけです。したがって、/ procをコピーするだけではいけない場合は、他にどの方法を使用する必要がありますか?

1
Leonid

procのmanページ を確認する必要があります。 /proc/[pid]/*エントリを見て、必要なファイルを選択します。

あなたはnotすべてをコピーしたくないのです。例として、共有などを含むプロセスのすべての仮想メモリである/proc/[pid]/memがあります。つまり、すべてのメモリのサイズです。さらに、プロセスがmemを所有しているか、ptracedであり、より高い特権で読み取られない限り、それを読み取ることはできません。 (そしてonly仮想サイズ-/proc/pid/status -> VmSize)–など。

または、単に実行可能ファイルへのリンクである/proc/PID/exestdinstdoutstderrおよびその他のファイル、パイプのファイル記述子を保持する/proc/PID/fd/*等.

他にもたくさんの特別なファイルとたくさんのリンクがあります(それらをすべてたどると、決して完了しません)。上記の人を読んでください、 kernel.orgからのドキュメント など。


さらに、ファイルはブロックデバイスファイルではありません。 procはメモリベースのファイルシステムであるため、これらはメモリ内に存在します。ある方法では、簡単にアクセスできるように配置されたカーネルへのウィンドウと呼ぶことができます。

したがって、これは、希望どおりの読み取りに関しても大きな利点です。情報はメモリに存在するため、ディスクI/Oがないため、非常に高速です。もちろん、データをディスクに書き込むことを選択した場合、これは失われますが、それでもディスクからディスクよりもはるかに高速です。


それを共有メモリと見なし、必要以上に複製しないようにしてください。あなたのタスクでは、おそらく/procのルートレベルにあるファイルも見るでしょう。 pstopfreeなどのソースコードを見て、他のツールがどのようにそれを行うかを簡単に紹介します。


多かれ少なかれいくつかの側面に触れるかもしれない他のいくつかの答えを書いています。あなたはそれのいくつかが役に立つと思うかもしれません:


編集:

コメントも。あなたは次のようなことをすることができます:

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

しかし、私は例えばのようないくつかのより低いレベルを使用したでしょう。上記の方法でファイルを解析するCは、必要なものに対して十分な速さではありません。

1時間に1回程度のコピーであれば、OKですが、たとえば秒または数分間隔ですら。

2
Runium