web-dev-qa-db-ja.com

プロセスがLinux上の別のプロセスのstdoutとstderrをインターセプトするにはどうすればよいですか?

実行を停止するはずのスクリプトがいくつかありますが、永遠にぶらぶらしています。彼らが何をSTDOUTとSTDERRに読みやすく書いているのか理解できる方法はありますか?

私は、例えば、しようとしました:

$ tail -f /proc/(pid)/fd/1

しかし、それは実際には機能しません。とにかくロングショットでした。

他のアイデアは?

strace自体は非常に冗長で、これを見ると判読できません。

注:私はonlyの出力に関心があり、それ以外には関心がありません。私は自分で他のことを理解することができます。この質問は、実行中のプロセスのstdoutとstderrにアクセスすることに焦点を当てていますafterそれを開始します。

うまくいくかどうかはわかりませんが、gdbを使用する メソッドを説明しているページをしばらく読んでいます

7
Jauco

Jaucoの回答を編集することは許可されていないので、私にとって効果的な完全な回答を提供します(ラッセルのページは、STDOUTのファイル記述子1を閉じると、次のcreat呼び出しはFD 1を開きます。

したがって、次のような単純なエンドレススクリプトを実行します。

import time

while True:
    print 'test'
    time.sleep(1)

それをtest.pyに保存し、実行

$ python test.py

PIDを取得します。

$ ps auxw | grep test.py

次に、gdbを添付します。

$ gdb -p (pid)

fdマジックを実行します:

(gdb) call creat("/tmp/stdout", 0600)
$1 = 3
(gdb) call dup2(3, 1)
$2 = 1

これでtail /tmp/stdoutを使用して、STDOUTに送信されていた出力を確認します。

「gdbメソッド」をラップし、いくつかの追加のタッチを追加するいくつかの新しいユーティリティがあります。現在使用しているものは「reptyr」(「Re-PTY-er」)と呼ばれています。 STDERR/STDOUTを取得するだけでなく、実際にプロセスの制御端末を変更します(以前に端末に接続されていなかった場合でも)。

これを最大限に活用するには、screenセッションを開始し、それを使用して実行中のプロセスをscreen内のターミナルに再接続し、安全に切り離して後で戻ってくることができるようにします。

それは人気のあるディストリビューションにパッケージ化されています(例: 'apt-get install reptyr')。

http://onethingwell.org/post/2924103615/reptyr

10
Mark Renouf

GDBメソッドはより良いようですが、straceでもこれを行うことができます。

$ strace -p <PID> -e write=1 -s 1024 -o file

straceのmanページから:

   -e write=set
               Perform a full hexadecimal and ASCII dump of all the
               data written to file descriptors listed in the spec-
               ified  set.  For example, to see all output activity
               on file descriptors 3 and 5 use -e write=3,5.   Note
               that  this is independent from the normal tracing of
               the write(2) system call which is controlled by  the
               option -e trace=write.

これは必要以上に出力しますが(16進数部分)、簡単にsedできます。

8
vherva

テキストをクリアするために、straceを使用して16進数の出力をデコードしました。

PID=some_process_id
Sudo strace -f -e trace=write -e verbose=none -e write=1,2 -q -p $PID -o "| grep '^ |' | cut -c11-60 | sed -e 's/ //g' | xxd -r -p"

他の答えからこのコマンドを組み合わせました。

5
Lari Hotari

straceは、-ewrite接尾辞だけではなく(=1接尾辞ではなく)、出力を大幅に減らします。また、GDB方式のIMOよりも少し単純です。

これを使用して、既存のMythTVエンコーディングジョブの進行状況を確認しました(エンコーディングプロセスを所有していないため、Sudo)。

$ ps -aef | grep -i handbrake
mythtv   25089 25085 99 16:01 ?        00:53:43 /usr/bin/HandBrakeCLI -i /var/lib/mythtv/recordings/1061_20111230122900.mpg -o /var/lib/mythtv/recordings/1061_20111230122900.mp4 -e x264 -b 1500 -E faac -B 256 -R 48 -w 720
jward    25293 20229  0 16:30 pts/1    00:00:00 grep --color=auto -i handbr

$ Sudo strace -ewrite -p 25089
Process 25089 attached - interrupt to quit
write(1, "\rEncoding: task 1 of 1, 70.75 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.76 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.77 % "..., 73) = 73
write(1, "\rEncoding: task 1 of 1, 70.78 % "..., 73) = 73^C
4
Jeff Ward

Reredirect( https://github.com/jerome-pouiller/reredirect/ )を使用できます。

タイプ

reredirect -m FILE PID

出力(標準およびエラー)はFILEに書き込まれます。

reredirect READMEでは、プロセスの元の状態を復元する方法、別のコマンドにリダイレクトする方法、またはstdoutまたはstderrのみをリダイレクトする方法についても説明しています。

3

あなたはあなたのオペレーティングシステムを述べていません、しかし私は刺し傷をして「Linux」と言うつもりです。

Stderrとstdoutに何が書き込まれているかを確認しても、おそらく役に立ちません。便利な場合は、スクリプトを開始する前にtee(1)を使用して、stderrとstdoutのコピーを取得できます。

Ps(1)を使用してwchanを検索できます。これにより、プロセスが何を待っているかがわかります。 straceの出力を見ると、出力の大部分を無視して、最後の(ブロックされた)システムコールを特定できます。それがファイルハンドルの操作である場合は、出力を後方に移動して、基になるオブジェクト(ファイル、ソケット、パイプなど)を特定できます。そこから答えが明確になる可能性があります。

また、プロセスにコアをダンプさせる信号を送信し、デバッガーとコアファイルを使用してスタックトレースを取得することもできます。

1
janm