防止Rake的sh命令回显命令

Ter*_*Dev 6 ruby rake

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

Jor*_*ing 13

解决这个问题有两个部分.第一种是传递verbose: false选项,这将阻止命令在执行之前被打印:

$ cat Rakefile
SECRET = 'foobarbaz'

task :foo do
  sh "echo #{SECRET} > secrets.txt", verbose: false
end

$ rake foo
(no output)
Run Code Online (Sandbox Code Playgroud)

但是,如果出现错误,这没有任何帮助,因为如果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...]
...
Run Code Online (Sandbox Code Playgroud)

解决方案在文档中sh暗示:

如果给出了一个块,则在命令完成时,将使用OK标志(零退出状态为true)和Process :: Status对象调用该块.如果没有块,则在命令退出非零时引发RuntimeError.

您可以在Rake源中查看默认行为的来源.那么,解决方案是提供我们自己的块:

$ 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]
...
Run Code Online (Sandbox Code Playgroud)

看起来不错!

如果你发现自己需要在多个地方,你可以写一个方便的方法; 这样的事情:

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
Run Code Online (Sandbox Code Playgroud)