Ruby 从FileUtils获取执行的命令?
将Ruby 从FileUtils获取执行的命令?,ruby,rubygems,Ruby,Rubygems,将:verbose标志传递给FileUtils命令时,该命令将打印到STDOUT。有没有一种方法可以捕获命令,以便在其他地方记录或使用它?如果查看FileUtils的源代码,它使用以下方法进行详细输出: def fu_output_message(msg) #:nodoc: @fileutils_output ||= $stderr @fileutils_label ||= '' @fileutils_output.puts @fileutils_label + msg end
:verbose
标志传递给FileUtils命令时,该命令将打印到STDOUT。有没有一种方法可以捕获命令,以便在其他地方记录或使用它?如果查看FileUtils
的源代码,它使用以下方法进行详细输出:
def fu_output_message(msg) #:nodoc:
@fileutils_output ||= $stderr
@fileutils_label ||= ''
@fileutils_output.puts @fileutils_label + msg
end
i、 e.它正在将消息写入@fileutils\u输出
,默认情况下使用$stderr
。似乎没有改变@fileutils\u输出的方法,但您可以添加一个:
module FileUtils
def FileUtils.fileutils_output=(new_out)
@fileutils_output = new_out
end
end
然后,如果要将命令捕获到文件中,可以执行以下操作:
my_fu_log = open('fu_log.log', 'w')
FileUtils.fileutils_output = my_fu_log
# FileUtils operations with :verbose => true here
my_fu_log.close
FileUtils.fileutils_output = $stderr # restore writing to stderr if you want
log = StringIO.new
FileUtils.fileutils_output = log
# FileUtils operations with :verbose => true here
# commands are in log.string
或者,如果你想把它们串起来,你可以:
my_fu_log = open('fu_log.log', 'w')
FileUtils.fileutils_output = my_fu_log
# FileUtils operations with :verbose => true here
my_fu_log.close
FileUtils.fileutils_output = $stderr # restore writing to stderr if you want
log = StringIO.new
FileUtils.fileutils_output = log
# FileUtils operations with :verbose => true here
# commands are in log.string
此外,还有一个模块FileUtils::Verbose
,它基本上包括FileUtils
(因此具有所有相同的方法),但默认选项为:Verbose=>true
,因此如果您想捕获大量命令,可以使用该模块,而不是每次都指定该选项。(您需要以与上面相同的方式将fileutils\u output=
方法添加到此模块。)
备选方案
正如在下面的评论中所说,另一种方法是重新分配$stderr
,但正如他所说的,这确实意味着写入stderr的所有内容(不仅仅是FileUtils
)都被重定向。如果所有的FileUtils
操作都是一次完成的,其间没有任何其他操作,那么这可能不是问题。因此,大致如下:
orig_stderr = $stderr # keep reference to original stderr
$stderr = my_fu_log
# use FileUtils here
$stderr = orig_stderr # restore stderr
最后,如果需要更多控制,您可以重新打开FileUtils
并覆盖fu_output_message(msg)
本身。为了添加到Mike的答案中(因为我无法评论),如果您希望以字符串形式获得输出,我创建了这个包装器def
:
def fileutil_out
out = StringIO.new
FileUtils.fileutils_output = out
yield
return out.string
end
mylog.info fileutil_out { FileUtils.chmod_R(0664, 'file.txt', :verbose => isVerbose) }
我最终没有使用它,因为我想在之后恢复到@fileutils\u output | |=stderr
。这是一个很好的答案。您可以做的另一件事是将$stderr重定向到您自己的对象,这样您就不必打开FileUtils类。当然,您将捕获打印到$stderr的非FileUtils方法的结果。@Joshua Yep,您是对的。实际上,我从重新分配$stdout
开始采用这种方法,但当这不起作用时(因为它改为写入$stderr
),我最终深入研究了文件utils
代码并得出了上述结论。太棒了!非常感谢您给出了明确的答案(以及这里的讨论!),这正是我所需要的:)