子プロセスの出力をリダイレクトする

子プロセスの出力をリダイレクトするには、いくつかの方法があります。

  1. using freopen(3)
  2. using dup(3)
  3. using popen(3)
  4. ...

What should one pick if all is wanted is to execute a child process and have it output saved in a given file, pretty much like the ls > files.txt works?

シェルが通常使っているのは何ですか?

2

2 答え

strace(1)であなたの好きなシェルが使っているものを見つけることができます。

1つの端末で:

echo $$

別の端末では:

strace -o /tmp/shell -f -p [PID from the first shell]

最初の端末で再び:

ls > files.txt

2番目の端末で strace(1)コマンドを実行し、/tmp/shell 出力ファイルを編集して、リダイレクトを行うために作られました。


freopen(3) manipulates the C standard IO FILE* pointers. All this will be thrown away on the other side of the execve(2) call, because it is maintained in user memory. You could use this after the execve(2) call, but that would be awkward to use generically.

popen(3) opens a single unidirectional pipe(7). This is useful, but extremely limited -- you get either the standard output descriptor or the standard input descriptor. This would fail for something like ls | grep foo | sort where both input and output must be redirected. So this is a poor choice.

dup2(2) will manage file descriptors -- a kernel-implemented resource -- so it will persist across execve(2) calls and you can set up as many file descriptors as you need, which is nice for ls > /tmp/output 2> /tmp/error or handling both input and output: ls | sort | uniq.

もう一つのメカニズムがあります: pty(7)の処理です。 openpty(3) forkpty(3)関数は、別のプログラムを処理するために特別に作成された新しい疑似端末デバイスを管理できます。 Unix環境での高度なプログラミング、第2版書籍には、非常に素晴らしい pty の例がありますプログラムをソースコードで使用していますが、これがなぜ有用か理解できない場合は、 script(1)プログラムを見てください - 新しい疑似端末を作成し、プログラムとの入出力をすべて記録し、後で再生または文書化するために記録をファイルに保管します。また、 expect(1)のような対話型プログラムのアクションを記述するのにも使用できます。

3
追加された

主に使用される dup2()を見つけることが期待されます。

Neither popen() nor freopen() is designed to handle redirections such as 3>&7. Up to a point, dup() could be used, but the 3>&7 example shows where dup() starts to creak; you'd have to ensure that file descriptors 4, 5, and 6 are open (and 7 is not) before it would handle what dup2() would do without fuss.

2
追加された
私はちょうどstraceの出力を調べました。@ sarnoldの提案に従って、bashは dup2()を使用します。あなたは正しいようです! +1
追加された 著者 Beginner,