web-dev-qa-db-ja.com

別の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を停止して出力をふるいにかけ、テキストが標準出力に出力されるのを見つけることができますが、それは非常に長くて混乱します。ローカルで作業しているかのようにスクリプト出力をライブで表示する方法を見つけたいのですが。

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

223
jwbensley

既存のプロセスをスパイするだけの場合は、_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_scome_ sysctlによって制御されます。

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

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

1 = stdout、2 = stderr

164
tvlooy

BSDでは、 watch を使用して、特定のttyをスヌープできます。

watch /dev/pts/0

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

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

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

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

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

バイナリ出力を扱う場合は、read-rを使用)およびprintf%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をプレーンテキストに解析する方法 at stackoverflow

10
kenorb

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

もう1つのオプションは、すべてをログファイルのようにファイルに書き込み、いつでも分析することです。すべての出力を保持する場合は、これが推奨されるアクションです。

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

  2. オンスクリーンXセッション用のVNCサーバーであるx11vncを使用します。

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

4
jippie

Nohupおよびのプロセスはいつでも起動できます

Nohup rsync source_file dest_file &

その後、次のコマンドを使用して、任意のttyからの進行状況を確認できます。

tail -f Nohup.out

これでうまくいきます。

3
Pablo Luna

straceの出力の解析:

トップアンサー を使用しました(プロセスIDは28223)...

> 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(16進数を出力するため、正規表現が正しく一致する)を呼び出し、最初の引数として9を使用してスクリプトにパイプ(STDERRを含む)します。

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

そして、出来上がり。プロセスの元のSTDOUT、改行、色などを出力します。

Attaching to process STDOUT

3
Jeff Ward

出力を取得するのが非常に簡単なのは、出力をファイルに取り込み、そのファイルをテーリングすることです。

行う場合:./ipcheck

INSTEAD DO:./ipcheck> [replacewithyourfilename]

これにより、スクリプトが配置されている出力ファイルが作成されます。次に、他のbashシェルからファイルをテールするだけです。

末尾[ファイル名を置き換える] -f

1
MrAllen

プロセスIDを取得してUSR1と通信できない

$pgrep -l '^ipchecker.sh$'

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

$ kill -USR1 PID

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

0
Saeed