すでに実行中のスクリプトからstderrをリダイレクトします


14

私は数日前からスクリプトを実行しています。stdoutをにリダイレクトしましたが$HOME/mylog、stderrには何もないと思ったため、stderrをリダイレクトしませんでした。突然何千もの行がstderrで出てきたので、私は仕事を中断しました。$HOME/myerrスクリプトを再起動することなく、これからstderrにリダイレクトできる方法はありますか?

ボックスにsudoアクセスがあり、それはOS Xです。

おそらくdtoolsトラップを使用しているものでしょうか?

スクリプトがこれまでに行った作業を失い、最初からやり直すことはできません。ディスク上の「メモリ内オブジェクトをダンプ」し、プログラムをフリーズし、変数(ファイル記述子など)を編集し、新しいコンテキストで再開する方法はありますか?


回答:


12

関連するインタープリターのプロセスをgdbにアタッチすると可能になると思います。このperl one-linerで試しました

 perl -e 'do { print "x\n"; sleep(1) } while(1)'

それは機能しますが、残念ながら、同様のbashスクリプトでは機能しません。


まず、出力をキャプチャするプロセスのPIDを把握する必要があります。次にgdb、別のターミナルで起動し、次のgdbコマンドを実行します

attach PID
call close(2)
call open("/abs/olu/te/path/filename", 65, 384)
detach PID

その後、書き込まれるデータ全体stderrがにリダイレクトされます/abs/olu/te/path/filename

  • attach PID プロセスをgdbに接続して停止します
  • call close(2)stderrプロセスのファイル記述子を閉じます(stdoutファイル記述子が1の場合)
  • call open(...) 新しいファイルを開き、新しく作成されたファイル記述子の最小の未使用整数を取得し、
  • detach PID プロセスを続ける

少なくとも私のマシンでは。最初の2行はPOSIX互換ですが、3行目は互換性がありません。

open3行目の2番目と3番目の引数は、に記載されていman 2 openます。私の場合、65はopenファイルを作成し、ファイルを書き込み専用O_WRONLY | O_CREAT(つまりで定義fcntl.h)で開くことを意味します。3番目の引数は、ユーザーに対して読み取りおよび書き込み権限を持つファイルを作成するようにopenに指示しますS_IWUSR | S_IRUSR(例:で定義sys/stat.h)。したがって、自分でマシンの適切な値を見つける必要があるかもしれません。


これは驚くほどうまくいきました...
Robottinosino

8

これは粗野な答えであり、他の誰かがより良くなることを願っていますが、他にアイデアが浮上していない場合は、gdbを添付してプロセスにいくつかのsyscallを強制します:

(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c

気の利いた。私はgdbがそれを行うことができることを知りませんでした。特定のファイル記述子番号に強制する方法はありますか?FD 1が使用されてopen()おらず、FD 1を取得している場合はどうですか?またはdup()、数回電話するだけですか?
パトリック

p open("errfile", O_WRONLY)本当にあなたのマシン上で動作しますか?
user1146332

あなたはに固執することができp dup2(xxx, 2)、その後、p close(xxx)どこxxxの戻り値ですopen。これは扱いにくいものです。他に選択肢がないことを確認するまで、長時間実行されるプロセスでこれらのコマンドを使用しないでください。
アランカレー

@ user1146332私が使用しているため、私はそれをしようとしたときにそれがなかった/dev/null私のようerrfileので、私は必要はありませんでしたO_CREAT。またO_WRONLY、マクロであるかどうかは、gdbがデバッグシンボルが利用可能でマクロが定義されている行でプロセスを停止したかどうかによって異なります。gdbを使用してプロセスにコードを挿入することは危険であり、これらのコマンドを理解せずにコピーするだけではいけません。
アランカレー

@AlanCurry一般的なデバッグ情報が利用できる場合、gdbはマクロを展開するとは思わない。特別なフラグを使用してソースをコンパイルする必要があります(こちらを参照)。それに加えて、システム上の任意の実行可能ファイルにデバッグ情報が含まれていることは非常にまれです(情報を単独でマクロ情報で拡張します)。しかし、一般的にコードインジェクションはお勧めできませんが、メリットがある場合があることに同意します。
user1146332
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.