While working on one of my pet projects of the moment, I struggled a bit to use file descriptors in a sub-process. I blindly assumed they would be inherited by child processes, which is not the case.

Here’s an example:

$ cat fd.rb

file = File.open 'file', 'w+'
fd = file.fileno
cmd = "date >&#{fd}"
pid = Process.spawn cmd
Process.wait pid
file.rewind
p file.read
$ ruby fd.rb
sh: 5: Bad file descriptor
""

The solution is to redirect the file descriptor opened in the parent process to the child process in Process.spawn options:

pid = Process.spawn cmd, {fd => fd}
$ ruby fd.rb
"Mon Mar 04 01:02:04 CET 2013\n"

Hopefully this will save some time for others :)