別のbashセッションで実行中のプロセスの出力を表示する方法は?


199

ローカルマシンで作業していたときから、リモートマシンで実行中のスクリプトを残しました。同じユーザーとして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出力を停止してふるいにかけると、テキストが標準出力に印刷されますが、非常に長く混乱しやすく、停止している間に何かを見逃す可能性があります。ローカルで作業しているかのように、スクリプト出力をライブで表示する方法を見つけたいと思います。

誰でもこれを改善できますか?明らかな答えは、リダイレクトまたはscreenセッションなどでスクリプトを再起動することです。これはミッションクリティカルなスクリプトではないので、それを行うことができます。むしろ、これは楽しい学習エクササイズだと思っています。


プロセスは仮想コンソールで実行されていますか、それともGUI / xtermのような環境で実行されていますか?
ジッピー

4
あなたは1つのシステムコールにstraceの出力を制限することができます:strace -p 4232 -e write
otokan

@jippieマシンは完全なGUI(Linux Mynt 13、XFCEデスクトップ)を実行しているので、gnome-terminalを起動しました。
jwbensley

3
このサイトには、少なくとも12個の同様の質問があります。ここでreptyrを探して、そのうちのいくつか(および回答)を見つけてください。
ステファンシャゼル

回答:


180

既存のプロセスをスパイするだけであればstrace -p1234 -s9999 -e write、1234がプロセスIDである場所を使用できます。(-s9999文字列を32文字に切り捨てたりwrite、出力を生成するシステムコールを回避したりします。)特定のファイル記述子に書き込まれたデータのみを表示する場合はstrace -p1234 -e trace= -e write=3、ファイル記述子3に書き込まれたデータのみを表示するなどの方法を使用できます(-e trace=システムを防ぎます記録からの呼び出し)。既に生成された出力は得られません。

出力のスクロールが速すぎる場合、のようなページャーにパイプするlessか、でファイルに送信できますstrace -o trace.log …

多くのプログラムでは、ptraceハックを使用して、現在の端末または新しいスクリーンセッションのいずれかに後続の出力を転送できます。実行中のプロセスを否認し、それを新しいスクリーンシェルに関連付ける方法を参照してくださいおよび他のリンクされたスレッド。

システムの設定方法によってはstrace、プロセスが追加の権限を持たないユーザーの下で実行されている場合でも、これらのコマンドをすべてrootとして実行する必要がある場合があることに注意してください。(プロセスが別のユーザーとして実行されている場合、またはsetuidまたはsetgidである場合はstrace、rootとして実行する必要があります。)ほとんどのディストリビューションは、プロセスが子をトレースすることのみを許可します(これにより、ある程度のセキュリティ上の利点が得られます。ただし、ファイルを変更して間接的な挿入を防ぐことはできません)。これはkernel.yama.ptrace_scomesysctl によって制御されます。


18
出力を標準出力のみに絞り込む方法はないと思いますか?
ジョナ

3
すべての議論を説明できますか?
ユーザー

6
nodejsから得ていた多くの出力には、多くのバックスラッシュと数字がありました。どのエンコーディングに含まれている可能性がありますか?プレーンテキストもたくさんありましたが、これで十分でした。
ThorSummoner

3
「すべての議論を説明できますか?」@user:man strace
Pistos

3
@RafaelMoni求めていることを実行するプログラムは、デバッガと呼ばれます。
ジル

139

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

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

1= stdout、2= stderr


7
「/ proc / <my pid> / fd / 1を読み取り用に開くことができません:そのようなデバイスまたはアドレスはありません」。
ヤロスラフニキテンコ

18
ええ<my pid>はプロセスIDで
-tvlooy

29
出力がttyに送信される(またはにリダイレクトされる/dev/null)場合、これは機能しません。出力がファイルにリダイレクトされる場合にのみ機能します。
mattdm

1
Ubuntu 16.04でテストしたが、動作しません。セッションでは次を実行します。ping google.es別のセッションではroot:としてtail -f /proc/`pgrep ping`/fd/2、何も表示されません。
david.perez

1
あなたが正しいです。fd 1と2は/ dev / ptsデバイスへのシンボリックリンクであるためです。-fa ptsデバイスをテーリングすることはできません。pingコマンドをcronjobとしてスケジュールしてから、同じことを行います。tail -fが動作します
tvlooy

9

BSDでは、どのwatchttyをスヌーピングするかを使用できます。たとえば、

watch /dev/pts/0

Linuxでは、screenやなどの前にプロセスがマルチプレクサーの下で実行されていなかった場合、それは不可能tmuxです。参照:Reptyr:実行中のプロセスを新しいターミナルに接続する

(例えば唯一の方法は、プロセスをデバッグするようですstracedtrace/ dtrussgdblldb、など)。

を使用したのでstrace、意味のある出力を取得するために、修飾式(などfile)でフィルタリングしてから、出力を解析する必要があります。以下に例を示します。

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

PIDで指定されたプロセスの書き込み操作(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をプレーンテキストに解析する方法 stackoverflowで


4
  1. リモートサーバーのログイン資格情報とGUIのディスプレイ番号で置き換えられるssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scale場所を使用して、リモート画面を覗くことができる場合があります。localhost:0.0

  2. を使用しますx11vnc。これは、画面上のXセッション用のVNCサーバーです。

  3. 6つの仮想コンソールのいずれかで実行する場合、適切なvcにsudo setterm -dump 2 -file /dev/stdout置き換えるtryを試してください2


4

名前付きパイプ(mkfifo)を作成し、そのファイルに書き込むことをお勧めします。次に、それから読みます。tail出力などを最小化するために、などの方法でいつでもそれを行うことができます。パイプをクリアする(パイプから読み取る)たびにクリアされるため、出力は保持されません。

もう1つのオプションは、すべてをファイルに書き込み(ログファイルのように)、その後いつでも分析することです。すべての出力を保持する場合は、これが優先アクションになります。


3

あなたはいつもwhithプロセスを起動することができnohupを

nohup rsync source_file dest_file &

次に、次のコマンドを使用して、ttyの進行状況を確認できます。

tail -f nohup.out

これは私には問題ありません。


6
この質問は、あなたの答えが示唆するようにバックグラウンドでプロセスを実行する方法ではなく、アラート実行プロセスの出力を表示する方法について
でした-jwbensley

実際、あなたの:nohupの言及は私を啓発します!ありがとう!
ナムG VU

1

出力を取得する非常に簡単な方法は、出力をファイルにキャプチャし、そのファイルをテーリングすることです。

行う場合:./ipcheck

INSTEAD DO:./ipcheck> [replacewithyourfilename]

これにより、スクリプトが置かれている場所に出力ファイルが作成されます。次に、他のbashシェルから、ファイルを単に末尾に移動できます。

テール[ファイル名と置き換える] -f


ファイルのリダイレクトでは、デフォルトでブロックベースのバッファリングを使用する傾向があり(参考文献を参照setbuf(3))、tail問題が生じる可能性があります。
-thrig

5
また、これは、新しいプロセスのstdoutをリダイレクトする方法ではなく、既に実行中のプロセスの出力を表示する方法に関する質問には役立ちません。
jwbensley

1

straceの出力の解析:

私が使用し、トップの答え(28223の私のプロセスIDを持つ)を...

> sudo strace -p28223 -s9999 -e write
...
write(9, "Info\nI\nCare\nabout", 55) = 55
...

私が気にしていると判断するためにwrite(9。(9は以下で使用されます。おそらくファイルハンドルであり、プロセスによって異なる可能性があります。)次に、それらを解析して表示するための簡単なRubyスクリプトを作成しました。

以下を貼り付けます /usr/bin/parse_strace.rb

#!/usr/bin/ruby

num = ARGV[0]
STDIN.each { |line|
  if (line.match(/write\(#{ num },\s*"(.*?)"/)) then
    puts $1.split('\x').map { |s| s.to_i(16).chr }.join()
  end
}

忘れないで chmod a+x /usr/bin/parse_strace.rb

私は、最初の引数としてstrace -xxスクリプトにパイピング(STDERRを含む)を呼び出し(16進数を出力するので、正規表現が適切に一致します)ます9

sudo sh -c 'strace -xx -p28223 -s9999 -e write 2>&1 | parse_strace.rb 9'

そして、できれば、プロセスの元のSTDOUT、改行、色、その他すべてを出力します!

プロセスSTDOUTへの接続


0

プロセスIDを取得してUSR1と通信することはできません

$pgrep -l '^ipchecker.sh$'

スクリプトのPIDを出力し、それを使用して

$ kill -USR1 PID

USR1は「ユーザー定義」シグナルであり、プログラムを作成した人は誰でも「シャットダウン」、「ログをダンプ」、「fooを1000回出力」などを意味することを理解しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.