每当我从rake中调用sh时,它经常回显将在它运行之前运行的命令。如何防止sh将命令记录到stdout。我想阻止这一点,因为我在调用的命令中有api键,而且我不想在构建日志中公开它们。
答案 0 :(得分:12)
解决这个问题有两个部分。第一种是传递verbose: false
选项,这将阻止命令在执行之前被打印:
$ cat Rakefile
SECRET = 'foobarbaz'
task :foo do
sh "echo #{SECRET} > secrets.txt", verbose: false
end
$ rake foo
(no output)
但是,如果出现错误,这没有任何帮助,因为如果Rake返回错误,Rake将打印失败的命令:
$ cat Rakefile
SECRET = 'foobarbaz'
task :foo do
sh "echo #{SECRET} > secrets.txt; exit 1", verbose: false
end
$ rake foo
rake aborted!
Command failed with status (1): [echo foobarbaz > secrets.txt; exit 1...]
...
该解决方案暗示in the docs for sh
:
如果给出了一个块,则在命令完成时,将使用OK标志(零退出状态为true)和Process :: Status对象调用该块。如果没有块,则在命令退出非零时引发RuntimeError。
您可以看到默认行为来自in the Rake source。那么,解决方案是提供我们自己的块:
$ cat Rakefile
SECRET = "foobarbaz"
task :foo do
sh "echo #{SECRET} > secrets.txt; exit 1", verbose: false do |ok, status|
unless ok
fail "Command failed with status (#{status.exitstatus}): [command hidden]"
end
end
end
$ rake foo
rake aborted!
Command failed with status (1): [command hidden]
...
看起来不错!
如果你发现自己需要在多个地方,你可以写一个方便的方法;像这样的东西:
def quiet_sh(*cmd)
options = (Hash === cmd.last) ? cmd.pop : {}
options = { verbose: false }.merge(options)
sh *cmd, options do |ok, status|
unless ok
fail "Command failed with status (#{status.exitstatus}): [command hidden]"
end
end
end
SECRET = "foobarbaz"
task :foo do
quiet_sh "do_secret_things"
end