防止Rake的sh命令回显命令

时间:2016-07-03 17:22:08

标签: ruby rake

每当我从rake中调用sh时,它经常回显将在它运行之前运行的命令。如何防止sh将命令记录到stdout。我想阻止这一点,因为我在调用的命令中有api键,而且我不想在构建日志中公开它们。

1 个答案:

答案 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