/dev/null にリダイレクトされた std 出力の検索

/dev/null にリダイレクトされた std 出力の検索

/dev/nullにリダイレクトされたstd出力を取得する方法はありますか?試してみましたが、tail -f /proc/{PID}/fd/1リダイレクト以外は機能しているようです/dev/null

つまり

tail -f /proc/${cmd_pid}/fd/1

有効cmd > log.txtだが無効cmd > /dev/null

- - - - - - - 更新 - - - - - - -

実際、log.txtstdoutが常に記録されている場合、大きな問題が発生します。プロセス自体を停止せずにロギングまたはロギングを停止するタイミングを制御できる場合は、これがcmd最善です。

tmpもしそうなら、stdoutをリソース集約的でないいくつかのファイルシステムにリダイレクトし、必要に応じてstdoutを検索できますか?

ベストアンサー1

これにより、cmd > /dev/nullシェルは新しいサブプロセスでfd 1を開き、/dev/nullそれを実行しますcmd

cmdfdが何に開いているかに関係なく、stdout(または、またはwrite(1, "output"...)などの他の書き込みシステム呼び出し)にデータを書き込むことを行います。sendsendmsgpwrite

Linuxでは、fd 1ファイルが開くマジック/proc/$pid_of_cmd/fd/1シンボリックリンクのみがあるため。/dev/nulltail -f thattail -f /dev/null

これらのwrite()システムコールを傍受してstrace結果をデコードできます。

strace -zqqs99999 -xxa0 -o /dev/stdout -e write -p "$pid" |
   perl -ne 'print chr(hex($_)) for /\\x(..)/g'

または:

strace -zqqs99999 -xxa0 -o /dev/stdout -e write -p "$pid" |
   perl -ne 'if (/^write\(1,/) {print chr(hex($_)) for /\\x(..)/g}'

write()sからstdout(fd 1)にのみ適用されます。または:

strace -yzqqs99999 -xxa0 -o /dev/stdout -e write -p "$pid" |
   perl -ne 'if (/^\Qwrite(1<\x2f\x64\x65\x76\x2f\x6e\x75\x6c\x6c>,\E "(.*)"/) {
     print chr(hex($_)) for $1 =~ /\\x(..)/g}'

sでstdout(fd 1)にのみ適用され、write()stdoutがで開いている場合にのみ適用されます/dev/null

出力をttyデバイス以外のデバイスにリダイレクトすると、行ではなくperlブロック単位でバッファリングが開始されるため、大量に数KBの出力しか表示されません。$|変数を次のように設定することで、このバッファリングを無効にできます1

strace -zqqs99999 -xxa0 -o /dev/stdout -e write -p "$pid" |
   perl -ne 'BEGIN{$| = 1}
             print chr(hex($_)) for /\\x(..)/g' > file

それともそうするのではなく、cmd > /dev/nullそうしてくださいcmd | cat > /dev/null

これでcmdstdoutはパイプになり、Linuxでは/proc/$pid_of_cmd/fd/1名前付きパイプのように動作します。そうすれば次のようになります。

kill -s STOP "$pid_of_cat"
cat "/proc/$pid_of_cmd/fd/1"

実際にパイプを新しいcatコマンドにリダイレクトします。

新しいパイプを終了した場合は、catそのパイプのタブを再度開くには、別のパイプ()を復元する必要がありますkill -s CONT "$pid_of_cat"/dev/null

プロセスの標準出力位置を実際に変更するには、デバッガを接続できます。

gdb --pid "$pid_of_cmd"

その後、gdbで:

call close(1)
p open("/path/to/some/file", 0x241, 0600)
detach

(0x241はO_WRONLY | O_TRUNC | O_CREATを意味します)

open()fd 1が返されることを確認してください。そうでない場合は、数回の通話dup2()と追加が必要になることがありますclose()

おすすめ記事