別のbashセッションで実行されているプロセスの出力をどのように表示できますか?

別のbashセッションで実行されているプロセスの出力をどのように表示できますか?

ローカルで作業している間は、リモートコンピュータで実行されるスクリプトが残ります。同じユーザーとしてSSH経由でコンピュータに接続しますps

$ ps aux | grep ipcheck
myuser  18386  0.0  0.0  18460  3476 pts/0    S+   Dec14   1:11 /bin/bash ./ipchecker.sh

ローカルセッションからstdoutとして印刷します(./ipchecker.shローカルターミナルウィンドウで実行されており、リダイレクトなし、使用なしscreenなど)。

とにかく、SSHセッション内で(停止せずに)この実行コマンドの出力を表示できますか?

これまで私が見つけた最良の方法はを使用することです。strace -p 18386しかし、画面を横切って飛び回る数多くのテキストが表示され、あまりにも詳細です。出力を停止しstraceてからフィルタリングしてstdoutに印刷されたテキストを見つけることができますが、非常に長くて混乱し、停止すると明らかに何かを見逃す可能性があります。まるでローカルで作業しているかのように、リアルタイムでスクリプト出力を表示する方法を見つけたいと思います。

誰でもこれを改善できますか?確実な答えは、セッションなどでスクリプトをリダイレクトまたは再起動することですscreen。これは仕事にとって重要なスクリプトではないので、そうすることができます。むしろ面白い学習運動だと思いました。

答え1

ファイルシステムを介して出力にアクセスできますproc

tail -f /proc/<pid>/fd/1

1=標準出力、2=標準エラー

(または@jmhostaletが言ったように:cat /proc/<pid>/fd/1tailが機能しない場合)

答え2

既存のプロセスのみを監視したい場合は、strace -p1234 -s9999 -e writeプロセスIDが1234の場所を使用できます。 (-s9999文字列を32文字に切り捨てたり、出力を生成したりするシステムコールを避けてください。)特定のwriteファイルディスクリプタに書き込まれたデータのみを表示するには、strace -p1234 -e trace= -e write=3ファイルディスクリプタ3に書き込まれたデータのみを表示などのものを使用できます。-e trace=システムコールが記録されます。)これにより、すでに生成された出力は提供されません。

出力が速すぎるまでスクロールすると、ポケットベルにパイプするか(たとえば)を使用してlessページに送信できますstrace -o trace.log …

多くのプログラムでは、ptrace ハッキングを使用して、後続の出力を現在の端末または新しい画面セッションに転送できます。バラより実行中のプロセスを拒否し、それを新しいスクリーンシェルに接続する方法は?そして他のリンクされたスレッド。

システムの設定方法によっては、straceプロセスが追加の権限なしでユーザーとして実行されている場合でも、これらのコマンドをすべてrootとして実行する必要があります。 (プロセスが別のユーザーとして実行されているか、setuidまたはsetgidの場合は、rootとしてstrace実行する必要があります。)ほとんどのディストリビューションでは、プロセスがサブアイテムを追跡することを許可します。(これはいくつかのセキュリティ上の利点を提供します。つまり、いくつかの直接的なマルウェアの注入を防ぎますが、ファイルの変更による間接的な注入を防ぎます。)これはkernel.yama.ptrace_scomesysctlによって制御されます。

答え3

BSDでは、次のものを使用できます。watch与えられたttyを受け取ります。

watch /dev/pts/0

screenLinuxでは、以前またはマルチプレクサでプロセスが実行されていない場合、これは不可能ですtmux。また見なさい:Reptyr:実行中のプロセスを新しい端末に接続する

唯一の方法は、プロセスをデバッグすることです(例:strace/、dtracedtrussgdb、、lldbなど。 )。

を使用したため、意味のある出力を取得するには、限定式(例)でフィルタリングしてから出力を解析する必要がありますstracefile例は次のとおりです。

strace -e trace=write -s1000 -fp 18386 2>&1 | grep -o '".\+[^"]"'

これは、PID(長さ1000)で指定されたプロセスの書き込み操作を印刷し(pgrep名前で照会用)、標準エラーを出力にリダイレクトし(フィルター用)、二重引用符で囲まれた文字列を印刷することです。

バイナリ出力を処理する場合は、read(with -r)とprintf (with %b)を使用してエスケープシーケンス文字を解析できます。

while read -r -t1 line; do printf "%b" $line; done

より多くのパラメータを確認してくださいhelp read-n改行ではなく特定の文字数の後に印刷するなど)。

以下はより完全な例です。

strace -e trace=write -s1000 -fp 18386 2>&1 \
| grep --line-buffered -o '".\+[^"]"' \
| grep --line-buffered -o '[^"]\+[^"]' \
| while read -r line; do
  printf "%b" $line;
done

プロセスを使用する例については、以下を確認してください。シェルでstraceをプレーンテキストに解析する方法は?スタックオーバーフロー時

答え4

stderrとstdoutを取得するには、次のように実行できます。

tail -f /proc/<pid>/fd/*

関連情報