シェル スクリプトを実行して、PID、STDERR、STDOUT、およびシェルの終了ステータスを取得しようとしています。
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 を使用して 3 つのハンドル自体を処理するため、PID を取得して open3 が行うことを実行できます。
その後、必ずファイルハンドルを閉じてください! 後でクリーンアップするこれの生成バージョンは、おそらくより理にかなっています。