【问题标题】:Ruby/Thor exit status in case of an error发生错误时的 Ruby/Thor 退出状态
【发布时间】:2013-06-21 18:24:09
【问题描述】:

我是 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​​)脚本中使用它,否则即使它应该终止脚本也会继续运行。后续错误可能难以分析。

我一定是错过了什么,因此我的问题是:

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

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

谢谢。

【问题讨论】:

    标签: ruby thor


    【解决方案1】:

    我知道这已经被回答了,但我认为这是一个更好的答案,所以我想我还是会贡献它。

    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? 方法,您将获得deprecation warning。这是为了处理令人困惑的默认行为。

    【讨论】:

      【解决方案2】:

      基于 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
      

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

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

      【讨论】:

        【解决方案3】:

        好问题。在寻找用于项目的thor 时,我也注意到了这一点。据我所知,这是预期的行为。这个pull request for 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
        

        【讨论】:

        • +1 因为它导致了黑客攻击(请参阅我的回答),尽管这不能直接使用,特别是作为 Ruby 之外的解决方案。
        猜你喜欢
        • 2018-11-26
        • 1970-01-01
        • 1970-01-01
        • 2021-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-20
        • 2020-07-19
        相关资源
        最近更新 更多