プログラムを適切に起動し、実行中の出力 (stdout と stderr) を後でリダイレクトできるようにするにはどうすればよいでしょうか?

プログラムを適切に起動し、実行中の出力 (stdout と stderr) を後でリダイレクトできるようにするにはどうすればよいでしょうか?

問題は単純です。スイッチをオン(およびオフ)にする必要な瞬間に実行中のプログラムの出力を取得します。より正確に言うと、標準出力 (およびエラー) を現在のシェルから別のシェル、 、/dev/nullファイルにリダイレクトしたり、元のシェルに戻したりできるようにしたいのです。

私は、自分が知っている事実を利用して、直接的(かつ安全)なものを探していますあらかじめ出力のオン/オフを切り替えます。回答も投稿します。


以下は私の最初の試みです。シェル番号 35 で作業するとします。

$ who am I                     # the command line to ask where am I
myuser  pts/35  ...            # The answer 

私の試みはその端末へのシンボリックリンクから始まります

ln -s /dev/pts/35  MyOutput  # The command to link

そのリンクにリダイレクトを設定してプログラムを起動するというアイデアです

./Execute_program > MyOutput

動作し、出力は端末にリダイレクトされますが、リンクを変更するコマンドを実行すると、

ln -sf  /dev/null  MyOutput

リンクが変わると、しかしリダイレクトは変更されない期待どおりです。実行中のプロセスでは変更されません。同じ方法で新しいプログラムを起動すると、リダイレクトはリンクの新しい規定に従います。
もう一度開始してリンクを に設定すると、出力は/dev/null期待どおりに抑制されますが、リンクを変更してもリダイレクトは変更されません。
リンクにリンクすると、同じ結果が得られます。 を使用してもhard link状況は変わりません。

悲しいことにシェルは起動時にコマンド ラインを展開します。

同様の方法でジョブを実行する可能性はありますか? または、リンクが変更されたことをプロセス (または PPID プロセス) に通知する方法を見つける必要がありますか?


ノート:

これは「実行中のプロセスの出力をリダイレクトするには?」シリーズの質問ですが、「あっ、プログラムを起動したけど、出力をリダイレクトするのを忘れてた。今それをやりたい」、その逆から:「後の段階で出力を別の場所にリダイレクトすることを明確な目的としてプログラムを起動するにはどうすればよいでしょうか?」

プログラムのソースコードを変更することが不可能(または不便)な場合に、このような手順を使用するつもりです
読むdisownある画面から別の画面に処理、使用、転送したり、デバッガーを使用してプロセスを傍受したりすることが可能になりますscreen。これらのソリューションはすべて、十分な経験と努力があれば機能しますが、一部には一定の割合のリスクも伴います。

答え1

mkfifo名前付きパイプを作成する、またはFIFO はシンボリック リンクを作成するのと同じ
くらい簡単で、シェルから許可されているすべてのリダイレクトを使用できます。

mkfifo MyOutput

ls -l与える

0 prw-r--r-- 1 My_username My_username  0 May 11 17:45 MyOut|

そのリンクにリダイレクトしてプログラムを起動できます

./Execute_program > MyOutput  &  cat MyOutput 

出力が端末に流れ始めます。

ctrl+を押すと、フローは中断されますが、実行中のプロセスは中断されません(またはのcようなものを使用する必要があります)。2 回目に尋ねると、kill pidkill %1
FIFO はターミナルにダンプするには (これも を使用cat MyOutput)、その瞬間から出力のダンプが開始されます。

注意と警告:

  • ダンプを要求しない限り、FIFOsすべての出力が保持されます。
    最初に要求すると、洗い流す全て。
  • 別のファイルにリダイレクト(または追加)できますcat MyOutput >> NewRealFile
  • cat MyOutput他の端末からも使えます!
  • 警告: 2つの異なるプログラム(またはインスタンス)に出力を同じものにリダイレクトするように要求すると、FIFOsフラックスはマージされます(アプリオリその行がどのプログラムからのものであるかを区別する方法)。
  • 警告: 2 回以上 (おそらく異なる端末から) 要求すると、要求ごとに 1 行が与えられ、出力が要求元に分割されます。安全な回避策があるかもしれません...

答え2

あなたの質問を正しく理解していれば:

script 1>>~/out.fifo 2>>~/error.fifo 

監視するには次のようにします。

watch cat ~/out.fifo

Fifoの代わりに実際のファイルを使用することもできます

script 1>/tmp/$0-out 2>/tmp/$0-error

その後、それらを tail -f すると、スクリプトを再度実行したときに置き換えられます。

私は2番目の方法、またはマルチプレクサ(つまりスクリーンや今週人気の生まれ変わりなど)を使用する方法を好みます。

screen -t "name" bash -c 'script'

それから

screen -r

をクリックして「監視」し、Ctrl+Ad で切り離します。

スクリプトの実行後に出力を確認したい場合は、スクリプトの最後で必ず一時停止してください。

答え3

私なら、出力をファイルにリダイレクトして、出力を見たいときにそのファイルを tailf します... また、出力がかなり長くなると思われる場合は、そのファイルのサイズを制限したり、出力がかなり速くなると思われる場合は、ファイルをディスクではなく RAM に書き込んだりすることもできますが、それらをどのように行うかは別の問題です。

関連情報