我想运行一个shell脚本并捕获PID,STDERR,STDOUT和shell的退出状态。使用Ruby 1.8.7,我可以执行shell并捕获PID,STDOUT,STDERR,状态吗?
我使用的是Ruby 1.8.7,因此Open3没有获取PID的方法。我尝试过使用open4 gem,但不幸的是在写入过程中挂起几个脚本,手动运行时运行良好。
我想找一个替代品。您的指导将非常感谢!
我想运行一个shell脚本并捕获PID,STDERR,STDOUT和shell的退出状态。使用Ruby 1.8.7,我可以执行shell并捕获PID,STDOUT,STDERR,状态吗?
我使用的是Ruby 1.8.7,因此Open3没有获取PID的方法。我尝试过使用open4 gem,但不幸的是在写入过程中挂起几个脚本,手动运行时运行良好。
我想找一个替代品。您的指导将非常感谢!
不幸的是,没有简单的方法来做到这一点。我试过PTY.spawn,但有时它会无法执行。如果你不能使用open3,那么你可以使用FIFO,但它有点混乱。下面是我在1.8.7上使用的解决方案:
# Avoid each thread having copies of all the other FDs on the fork
def closeOtherFDs
ObjectSpace.each_object(IO) do |io|
unless [STDIN, STDOUT, STDERR].include?(io)
unless(io.closed?)
begin
io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
rescue ::Exception => err
end
end
end
end
end
# Utilities for fifo method
require 'tempfile'
def tmpfifo
# Use tempfile just to manage naming and cleanup of the file
fifo = Tempfile.new('fifo.').path
File.delete(fifo)
system("/usr/bin/mkfifo",fifo)
#puts "GOT: #{fifo} -> #{$?}"
fifo
end
# fifo homebrew method
def spawnCommand *command
ipath = tmpfifo
opath = tmpfifo
#epath = tmpfifo
pid = fork do
#$stdin.reopen(IO.open(IO::sysopen(ipath,Fcntl::O_RDONLY)))
$stdin.reopen(File.open(ipath,'r'))
$stdout.reopen(File.open(opath,'w'))
#$stderr.reopen(File.open(epath,'w'))
$stderr.close
closeOtherFDs
exec(*command)
exit
end
i = open ipath, 'w'
#i.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC) # Doesn't work? Use closeOtherFDs
o = open opath, 'r'
#e = open epath, 'r'
e = nil
[o,i,e].each { |p| p.sync = true if p }
[o,i,e]
end
不是,它不干净。但是因为它使用fork并且处理三个句柄本身,那么你可以得到PID并完成open3的功能。
请务必在关闭文件句柄之后!这种清理后的产量版本可能会更有意义。
作为一个说明,我有'closeOtherFDs'例程来查找和关闭所有stdin/stdout/stderr对象的原因是因为我如果你只是产卵了几个,那么你可以把这个代码拿出来 –
而且,我刚刚意识到我粘贴的代码是关闭stderr,b你应该能够弄清楚如何使用tmpfifo。 –
感谢@David Ljung Madison在帮助我的时候,我只是想保持简单,因为我有成千上万的过程被产生。无论如何,我已经使用反向执行的方式根据退出状态来移动输出。再次感谢!! – Jay
您可以通过Process.pid获取Ruby中的当前PID。让我知道如果这有助于 – Raghu
谢谢Raghu,我正在寻找每个shell进程的PID产生,而不是当前进程的PID,对不起,如果我的写作误导你.. – Jay
你可以发布一些示例代码,所以我们可以尝试重现这个问题? – iblue