ローカルで作業していたときから、リモートマシンでスクリプトを実行したままにしておきました。 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
セッションなどでスクリプトを再起動することです。これはミッションクリティカルなスクリプトではないので、私はそれを行うことができました。むしろ、これは楽しい学習課題だと思います。
既存のプロセスをスパイするだけの場合は、_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
BSDでは、 watch
を使用して、特定のttyをスヌープできます。
watch /dev/pts/0
Linuxでは、screen
やtmux
など、以前にマルチプレクサーでプロセスが実行されていなかった場合、それは不可能です。参照: レプティル:実行中のプロセスを新しいターミナルに接続する
プロセスをデバッグするのが唯一の方法のようです(例:strace
、dtrace
/dtruss
、 gdb
、lldb
など)。
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
名前付きパイプ(mkfifo
)を作成し、そのファイルに書き込むことをお勧めします。次に、それを読みます。 tail
などを使用して、出力を最小限に抑えるなど、いつでもそれを行うことができます。パイプをクリアする(パイプから読み取る)と、パイプはクリアされるため、出力は保持されません。
もう1つのオプションは、すべてをログファイルのようにファイルに書き込み、いつでも分析することです。すべての出力を保持する場合は、これが推奨されるアクションです。
ssh localhost 'DISPLAY=:0.0 xwd -root' | xwud -scale
を使用してリモート画面を覗くことができる場合があります。ここで、localhost
はリモートサーバーのログイン認証情報で置き換え、:0.0
はGUIのディスプレイ番号で置き換えます。
オンスクリーンXセッション用のVNCサーバーであるx11vnc
を使用します。
6つの仮想コンソールのいずれかで実行している場合は、Sudo setterm -dump 2 -file /dev/stdout
を試してください。この場合、2
を適切なvcに置き換えます。
Nohupおよび&のプロセスはいつでも起動できます
Nohup rsync source_file dest_file &
その後、次のコマンドを使用して、任意のttyからの進行状況を確認できます。
tail -f Nohup.out
これでうまくいきます。
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、改行、色などを出力します。
出力を取得するのが非常に簡単なのは、出力をファイルに取り込み、そのファイルをテーリングすることです。
行う場合:./ipcheck
INSTEAD DO:./ipcheck> [replacewithyourfilename]
これにより、スクリプトが配置されている出力ファイルが作成されます。次に、他のbashシェルからファイルをテールするだけです。
末尾[ファイル名を置き換える] -f
プロセスIDを取得してUSR1と通信できない
$pgrep -l '^ipchecker.sh$'
スクリプトのPIDを出力し、それを使用して
$ kill -USR1 PID
USR1は「ユーザー定義」の信号であることを理解しています。つまり、プログラムを作成した人なら誰でも、「シャットダウン」、「ログをダンプ」、「fooを1000回出力」などの意味で使用できます。