9

我是 Thor(和 Ruby)的新手,我正在考虑在构建脚本中使用它,因为据说它可以替代 Rake(因此是 Make)。但是经过短暂的试用后,我对它返回的错误状态感到困惑。我很快浏览了wiki,但没有看到任何提及。

仅使用第一个“简单示例”,test.thor

class Test < Thor
  desc "example", "an example task"
  def example
    puts "I'm a thor task!"
  end
end

版本 #:

eruve>thor version
Thor 0.18.1

我故意尝试了以下错误命令:

eruve>ruby --version; thor test:example badarg; echo exit status: $?

ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-darwin10.8.0]
ERROR: thor example was called with arguments ["badarg"]
Usage: "thor test:example".
exit status: 0

所以,有一个错误,但它仍然以状态 0 退出......这意味着我宁愿不在(非 ruby​​)脚本中使用它,否则即使它应该终止脚本也会继续运行。随后的错误可能难以分析。

我一定遗漏了一些东西,因此我的问题是:

  • 如果出现错误(配置文件等),是否有一种简单的方法可以默认获取非零状态?

  • 如果没有,我应该怎么做才能让它正确?

谢谢你。

4

3 回答 3

22

我知道这已经得到了回答,但我认为这是一个更好的答案,所以我想无论如何我都会贡献它。

Thor 有一种方法可以用来改变行为,因此错误会导致非零退出代码。它没有很好地记录(恕我直言)。

class Test < Thor
  def self.exit_on_failure?
    true
  end

  desc "example", "an example task"
  def example
    puts "I'm a thor task!"
  end
end

对此的默认设置是莫名其妙false。我不知道为什么有人会希望它个人表现得那样。Thor issue 244也解决了这个问题。

更新:从 Thor 1.0.0 开始,如果您提供自己的方法,您将收到弃用警告。这是为了处理令人困惑的默认行为。exit_on_failure?

于 2013-08-28T13:57:09.990 回答
3

基于 bundler 的解决方案(非常感谢@fontno),以及我这边的更多调查,这里有一个 hack,以便让它与普通 shell 一起工作。警告:它不优雅,打印出异常堆栈废话,但我认为这有效(请不要犹豫告诉我)。

class Thorough < Thor
  ENV["THOR_DEBUG"] = "1"
  check_unknown_options!
private
  def subcommand(*_) super subcommand(*_)
  rescue Thor::Error => e
    $stderr.puts e.message
    exit 1
  end
end

class Test < Thor#ough
  desc "example", "an example task"
  def example
    puts "I'm a thor task!"
  end
end

如上所写,它的行为与以前相同(我相信)。现在,在删除#from之后Thor#ough,如果 Thor 提出了 an ,它应该以状态 1 退出Error,从而允许从例如非 ruby​​ shell 进行一些控制。

eruve>thor test:example badarg; echo $?
/Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/base.rb:482:in `handle_argument_error': ERROR: thor example was called with arguments ["badarg"] (Thor::InvocationError)
Usage: "thor test:example".
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/command.rb:35:in `rescue in run'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/command.rb:21:in `run'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/invocation.rb:120:in `invoke_command'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor.rb:363:in `dispatch'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/base.rb:439:in `start'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/runner.rb:36:in `method_missing'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/command.rb:29:in `run'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/command.rb:128:in `run'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/invocation.rb:120:in `invoke_command'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor.rb:363:in `dispatch'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/lib/thor/base.rb:439:in `start'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/gems/thor-0.18.1/bin/thor:6:in `<top (required)>'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/bin/thor:23:in `load'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/bin/thor:23:in `<main>'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/bin/ruby_noexec_wrapper:14:in `eval'
    from /Users/eruve/.rvm/gems/ruby-2.0.0-p195/bin/ruby_noexec_wrapper:14:in `<main>'
1

eruve>thor test:example; echo $?
I'm a thor task!
0

eruve>thor test:example badarg 2>/dev/null; echo $?
1

干杯。PS:我想知道,雷神有很多这样的陷阱吗?如果这是一种预期的行为,那么它的目的/理念与我的项目需求不兼容......黑客不是一个可靠的解决方案。

于 2013-06-22T05:28:20.077 回答
1

好问题。thor在寻找用于项目的方法时,我也注意到了这一点。据我所知,这是预期的行为。这个拉取请求bundler有一个有趣的解决方案,可能适合您。

他们启用了 thor 调试标志,以便他们可以捕获错误并设置适当的退出状态

# bin/bundle

Bundler.with_friendly_errors {
    # Set debug flag so we can rescue Thor::error's
    # and set the correct exit code.
    ENV["THOR_DEBUG"] = "1"
    Bundler::CLI.start
}


# friendly_errors

rescue Thor::UndefinedCommandError => e
    Bundler.ui.error e.message
    exit 15
  rescue Thor::Error => e
    Bundler.ui.error e.message
    exit 1
于 2013-06-21T20:34:38.013 回答