質問: あるプログラム中で`printf("teratail\n");`のように書いたとします。 このプログラムのコンパイル後のファイル名をprogramとし、そのプログラムがあるディレクトリまで`cd`コマンドで移動し、`./program`で実行しました。 このとき画面(ターミナル、端末、コマンドプロンプト)には「teratail」と表示されると思います。 次にこのプログラムをサービスやデーモンなどのように起動させておくとします。 このとき、端末を開いてる時にそのプログラムが`printf`するタイミングになっても画面に文字列`teratail`が現れたりすることはありませんよね? わたしの印象では直接実行、つまり`./program`のように端末から能動的に実行したもの以外`printf`などの出力は見られないと思うのですが、プログラムが実行した`printf("teratail\n");`の出力はどこにいくのでしょうか? 「標準入力・標準出力」などは1つだけしかないと思っていたのですが、プログラムごとに作られる(?)のでしょうか? わかりにくい説明ですみません。 不明な点があったら指摘していただけるとありがたいです。 また、 もしこの出力を外部からキャッチする方法があるなら教えていただきたいです。
回答: 標準出力というのは、プロセスごとに存在します。 具体的に言うと、プロセスごとに存在するファイルディスクリプタの配列の添え字1のデータのことです。 各ファイルディスクリプタは、(1)なんらかのファイルに繋がっている(オープンされている)、(2)どこにも繋がっていない(クローズされている)のどちらかです。 ファイルディスクリプタは、プロセスが生成された時に、親プロセスからコピーされます。 端末のbashから起動したプロセスであれば、bashの標準入力(添え字0)、標準出力(添え字1)、標準エラー出力(添え字2)は、みんなその端末に繋がっており、特に指定していない限り、添え字3以降のファイルディスクリプタはクローズされた状態です。 bashからプログラム起動時に標準出力をリダイレクトした場合は、子プロセス生成後に標準出力をリダイレクト先に繋ぎ直した後で、プログラムに制御を移します。 もちろん、bash自体の標準出力がリダイレクトされている場合は、そのbashから起動されたプログラムもデフォルトでは親のbashと同じ所にリダイレクトされます。親のコピーなので。 デーモンの場合は、デーモンプログラムの初期化処理の中で標準入力等を/dev/nullに繋ぎ直すのが普通です。 ファイルディスクリプタは、プロセスの中のローカルなデータであり、外からコマンドでどうにかすることは出来ないので、他の方の回答にあるように、デバッガでそのプロセス自体を書き換えるしかないです。