进程#spawn导致"没有这样的文件或目录 - 打开(Errno :: ENOENT)"

时间:2014-09-06 17:00:06

标签: ruby process io-redirection

将输出重定向到文件时,只是我或者Ruby Process#spawn中是否存在错误? The documentation说:

redirection:
  key:
    FD              : single file descriptor in child process
    [FD, FD, ...]   : multiple file descriptor in child process
  value:
    FD                        : redirect to the file descriptor in parent process
    string                    : redirect to file with open(string, "r" or "w")
    [string]                  : redirect to file with open(string, File::RDONLY)
    [string, open_mode]       : redirect to file with open(string, open_mode, 0644)
    [string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
    [:child, FD]              : redirect to the redirected file descriptor
    :close                    : close the file descriptor in child process
  FD is one of follows
    :in     : the file descriptor 0 which is the standard input
    :out    : the file descriptor 1 which is the standard output
    :err    : the file descriptor 2 which is the standard error

所以我应该能够将密钥设为[:out, :err],将值作为表示文件名的字符串,但是:

% ruby -e 'spawn("ps -ef", [:out, :err] => "foo")'
-e:1:in `spawn': No such file or directory - open (Errno::ENOENT)
        from -e:1:in `<main>'

(顺便说一句,我已经用2.1.2和2.0.0进行了测试,但似乎没有任何区别。)

如果我第一次创建文件,行为会改变:

% touch foo
% ruby -e 'spawn("ps -ef", [:out, :err] => "foo")'

但是没有任何内容写入文件,从重定向键中删除:err证明在设置重定向时出现了问题:

% cat foo
% ruby -e 'spawn("ps -ef", [:out] => "foo")' 2>err
% cat err
ps: write error: Bad file descriptor

解决这种奇怪现象并获得我想要的行为相当容易,例如。

% rm -f foo
% ruby -e 'Process.waitpid(spawn("ps -ef", [:out, :err] => ["foo", "w"]))'
% wc foo
  503  4422 36470 foo

% rm -f foo
% ruby -e 'Process.waitpid(spawn("ps -ef", :out => "foo", :err => :out))'
% wc foo
  503  4422 36470 foo

但由于文件明显与实际行为不符,因此我浪费了30分钟,所以我很想知道它是真正的错误还是我的误解。

我怀疑当使用在单个FD内组合多个Array的表单时,Ruby会停止尝试自动检测它是否应该在读取时打开FD或写入模式,只在读取模式下打开。然后,当进程尝试写入它时,这会失败。当您尝试在同一FD内混合输入/输出Array时,似乎可以通过Ruby没有任何错误甚至警告来证实这一点:

% yes | head -n3 > foo
% ruby -e 'Process.waitpid(spawn("wc", [:in, :out] => "foo"))'
wc: write error
% cat foo
y
y
y
% yes | head -n3 > foo
% ruby -e 'Process.waitpid(spawn("wc", [:in, :out] => ["foo"]))'
wc: write error
% cat foo
y
y
y

但我确信其他人可以提供更好的解释。

0 个答案:

没有答案