[ruby-dev:31693] Re: IO.sysdup2, IO.sysdup, IO.sysclose

From: Tanaka Akira <akr@...>
Date: 2007-09-01 08:39:51 UTC
List: ruby-dev #31693
In article <20070901155458.42a561ea.sheepman@sheepman.sakura.ne.jp>,
  sheepman <sheepman@sheepman.sakura.ne.jp> writes:

> sh などでの 3>&1 の 3 というのは一時変数みたいなものなので、
> 3 を具体的に指定できる必要性はないはずです。例えば、
>
> $ command 3>&1 >/dev/null 2>&3
>
> みたいなことを Ruby でしたいときは
>
> fd3 = $stdout.dup
> $stdout.reopen('/dev/null')
> $stderr.reopen(fd3)
>
> とすれば良いのではと思うのですが。fd を具体的に指定できた方がうれしいのは
> どういったばあいでしょうか?

はい。固定された番号に意味があるケースがあります。

たとえば、DJB の checkpassword を呼び出すときには 3番の fd
を用意してやる必要があります。

他にも、lpr のフィルタは accounting file につながってる fd
を 3番にして起動しなきゃいけないとか、CUPS の backend とか、
Courier のフィルタとか、この類の動作はそれほど珍しくありませ
ん。(経験があるわけじゃないですが、検索すればそれなりに見つ
かります)

この、親プロセスが特定の番号で fd を用意し、子プロセスがそれ
を使う、というやりかたはその最たるものが標準入力、標準出力、
標準エラー出力の 0, 1, 2 番なわけですが、3番以降を使用しよう
と思う人がいてもおかしくなくて、実際にいる、というわけです。

そういう用途を一般的に支援したいとした場合、dup2 で特定の番
号の fdを直接指定できれば、ものごとが簡単になります。

まぁ、IO.new(fd).close と (EBADF を無視して) やってから
IO#dup を目的の fd が得られるまで繰り返し、不要なものをぜん
ぶ close するとすればできなくはありませんが、それはかなり迂
遠ですよね。一皮剥けば dup2 があるのに、なんでそんな苦労をし
ないといけないのだろうか、と思ってしまいます。
-- 
[田中 哲][たなか あきら][Tanaka Akira]

In This Thread